#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
bool IsLeapYear(uint16_t year)
{
if (year % 100 == 0)
{
return year % 400 == 0;
}
else
{
return year % 4 == 0;
}
}
typedef enum Month
{
Jan = 0,
Feb,
Mar,
Apr,
May,
Jun,
Jul,
Aug,
Sep,
Oct,
Nov,
Dec,
} Month;
uint16_t DaysInMonth(Month month)
{
switch (month)
{
case Jan:
{
return 31;
};
case Feb:
{
return 28; // normally 28, leap year 29, the +1 will be handled else-where.
};
case Mar:
{
return 31;
};
case Apr:
{
return 30;
};
case May:
{
return 31;
};
case Jun:
{
return 30;
};
case Jul:
{
return 31;
};
case Aug:
{
return 31;
};
case Sep:
{
return 30;
};
case Oct:
{
return 31;
};
case Nov:
{
return 30;
};
case Dec:
{
return 31;
};
default:
{
fprintf(stderr, "Unknown month: %d\n", month);
} break;
}
}
typedef enum Week
{
Sun = 0,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat,
} Week;
// 1 Jan 1900 was a Monday, so 7 Jan 1900 is a Sunday.
// +7 every seven days is another Sunday.
// Idea: Track the first day of each month.
// From 1 Jan 1901 to 31 Dec 2000, how many first days of a month fell on a Sunday?
void Solve()
{
uint64_t count = 0;
Week FirstDayOfEachMonth = Mon;
for (uint16_t year = 1900; year <= 2000; year++)
{
for (Month month = Jan; month <= Dec; month++)
{
uint16_t days = DaysInMonth(month);
if (IsLeapYear(year) && month == Feb)
{
days += 1;
}
if (year > 1900 && FirstDayOfEachMonth == Sun)
{
count += 1;
}
FirstDayOfEachMonth = (FirstDayOfEachMonth + (days % 7)) % 7;
}
}
printf("%lu\n", count);
}
int main()
{
Solve();
return 0;
}
; sbcl --script 19.lisp
(defun is-leap-year (year)
(if (= (mod year 100) 0)
(= (mod year 400) 0)
(= (mod year 4) 0)))
(defun month-days (month)
(cond
((= month 1) 31)
((= month 2) 28); +1 in leap year
((= month 3) 31)
((= month 4) 30)
((= month 5) 31)
((= month 6) 30)
((= month 7) 31)
((= month 8) 31)
((= month 9) 30)
((= month 10) 31)
((= month 11) 30)
((= month 12) 31)))
(defvar *count* 0)
(defvar *start-day-of-the-month* 0); 0 - Sun, 1 - Mon, ..., 6 - Sat
(defun Counting-Sundays ()
(do ((year 1900 (+ year 1)))
((= year 2001))
(do ((month 1 (+ month 1)))
((= month 13))
(let ((days (month-days month)))
(when (= month 2) (incf days 1))
(when (and (> year 1900) (= *start-day-of-the-month* 0)) (incf *count* 1))
(setf *start-day-of-the-month* (mod (+ *start-day-of-the-month* (mod days 7)) 7)))))
(format t "~A~%" *count*))
(Counting-Sundays)