""" 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()