84
solutions/0019.CountingSundays/euler_19.py
Normal file
84
solutions/0019.CountingSundays/euler_19.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""
|
||||
You are given the following information, but you may prefer to do some research for yourself.
|
||||
|
||||
- 1 Jan 1900 was a Monday.
|
||||
- Thirty days has September, April, June and November.
|
||||
- All the rest have thirty-one, Saving February alone,
|
||||
- Which has twenty-eight, rain or shine. And on leap years, twenty-nine.
|
||||
- A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
|
||||
|
||||
How many Sundays fell **on the first of the month** during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
|
||||
def timer(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
start_time = time.time()
|
||||
result = func(*args, **kwargs)
|
||||
end_time = time.time()
|
||||
print(f"Execution time: {end_time - start_time} seconds")
|
||||
return result
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def is_leap_year(year: int) -> bool:
|
||||
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
|
||||
|
||||
|
||||
def days_in_years(years: list[int]) -> int:
|
||||
leapyears = [year for year in years if is_leap_year(year)]
|
||||
return sum([366 if year in leapyears else 365 for year in years])
|
||||
|
||||
|
||||
def count_sundays(start_year: int | str, end_year: int | str) -> int:
|
||||
start_year = int(start_year) if isinstance(start_year, str) else start_year
|
||||
end_year = int(end_year) if isinstance(end_year, str) else end_year
|
||||
if start_year < 1900 or start_year > end_year:
|
||||
raise ValueError(f"Invalid year range {start_year} to {end_year}")
|
||||
last_days = days_in_years(list(range(1900, start_year)))
|
||||
year_list = list(range(start_year, end_year + 1))
|
||||
days = days_in_years(year_list) + (last_days % 7)
|
||||
sundays = days // 7
|
||||
return sundays
|
||||
|
||||
|
||||
def days_month(year: int, month: int) -> int:
|
||||
if month in [1, 3, 5, 7, 8, 10, 12]:
|
||||
return 31
|
||||
elif month in [4, 6, 9, 11]:
|
||||
return 30
|
||||
elif month == 2:
|
||||
return 29 if is_leap_year(year) else 28
|
||||
else:
|
||||
raise ValueError(f"Invalid month {month}")
|
||||
|
||||
|
||||
def days_sunday_month(start_year: int, end_year: int) -> int:
|
||||
count = 0
|
||||
outday = days_in_years(list(range(1900, start_year))) % 7
|
||||
for year in range(start_year, end_year + 1):
|
||||
for month in range(1, 13):
|
||||
if outday == 6:
|
||||
count += 1
|
||||
outday = (outday + days_month(year, month)) % 7
|
||||
return count
|
||||
|
||||
|
||||
@timer
|
||||
def main() -> None:
|
||||
print(f"Number of Sundays between 1901 and 2000: {count_sundays(1901, 2000)}")
|
||||
|
||||
|
||||
@timer
|
||||
def main_first_day() -> None:
|
||||
print(
|
||||
f"Number of Sundays on the first of the month between 1901 and 2000: {days_sunday_month(1901, 2000)}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main_first_day()
|
||||
Reference in New Issue
Block a user