Counting Sundays
Given that 1 January 1900 was a Monday, determine the number of Sundays that fell on the first of the month during the period 1 January 1901 to 31 December 2000 (inclusive).
Problem Statement
This archive keeps the full statement, math, and original media on the page.
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)?
Problem 19: Counting Sundays
Mathematical Development
Definition 1 (Day-of-week encoding). Encode days of the week as elements of : Sunday , Monday , Tuesday , …, Saturday .
Definition 2 (Leap year). A year in the Gregorian calendar is a leap year if and only if
Lemma 1 (Month lengths). Let denote the number of days in month of year . Then:
where is the Iverson bracket.
Proof. This is the defining rule of the Gregorian calendar.
Theorem 1 (Day-of-week advancement). If the 1st of month in year falls on day , then the 1st of the subsequent month falls on day
Proof. The first day of the next month is exactly days later. Since the day-of-week function is periodic with period 7, .
Definition 3 (Day-of-week residues modulo 7). The residues for a non-leap year are:
| Month | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | 0 | 3 | 2 | 3 | 2 | 3 | 3 | 2 | 3 | 2 | 3 |
In a leap year, only February changes: .
Theorem 2 (Gregorian cycle). The Gregorian calendar has a period of exactly 400 years, comprising days.
Proof. In 400 years there are days, where is the number of leap years (every 4th year except centuries, plus every 400th). Since , the cycle is an exact multiple of weeks, so the day-of-week pattern repeats exactly every 400 years.
Corollary 1 (Expected count heuristic). The period 1901—2000 contains first-of-month dates. If these were uniformly distributed over the 7 weekdays, we would expect Sundays. The exact answer 171 is consistent with near-uniformity.
Theorem 3 (Sequential computation). Starting from the known anchor (Monday, 1 January 1900), iteratively applying Theorem 1 through all months from January 1900 to December 2000, and counting those months in the range 1901—2000 where , yields the exact count of first-of-month Sundays.
Proof. The iteration is a faithful simulation of the Gregorian calendar. Each application of Theorem 1 is exact (no approximation). The count records precisely those first-of-month days falling on Sunday within the specified range.
Editorial
We simulate the calendar month by month, keeping track of the weekday of the first day of the current month. Beginning from the known fact that 1 January 1900 was a Monday, we iterate through all months up to the ending year, count the months in the target interval whose first day is Sunday, and advance the weekday by the month length modulo 7. This is sufficient because every month in the range is visited exactly once.
Pseudocode
Algorithm: Counting Sundays on the First of the Month
Require: The date range from 1 January 1901 through 31 December 2000, together with the fact that 1 January 1900 was a Monday.
Ensure: The number of months in the target range whose first day is a Sunday.
1: Initialize the weekday of the first day of the current month and set count ← 0.
2: For each month from January 1900 through December 2000 do:
3: If the current year lies in 1901, ..., 2000 and the current first weekday is Sunday, increment count.
4: Advance the weekday by the length of the current month, using the leap-year rule for February.
5: Return count.
Complexity Analysis
Proposition 1. The algorithm runs in time and space, where .
Proof. The outer loop runs iterations, each with 12 inner iterations of work (one comparison, one modular addition). The total is operations. Only a constant number of integer variables are maintained.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main() {
auto isLeap = [](int y) {
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
};
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int w = 1, count = 0; // 1 Jan 1900 = Monday
for (int y = 1900; y <= 2000; y++) {
for (int m = 0; m < 12; m++) {
if (y >= 1901 && w == 0) count++;
int d = (m == 1 && isLeap(y)) ? 29 : days[m];
w = (w + d) % 7;
}
}
cout << count << endl;
return 0;
}
"""Project Euler Problem 19: Counting Sundays"""
def main():
days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
is_leap = lambda y: (y % 4 == 0 and y % 100 != 0) or y % 400 == 0
w, count = 1, 0 # 1 Jan 1900 = Monday (1); Sunday = 0
for y in range(1900, 2001):
for m in range(12):
if y >= 1901 and w == 0:
count += 1
d = 29 if m == 1 and is_leap(y) else days[m]
w = (w + d) % 7
print(count)