John Conway's Doomsday algorithm, implemented in C++ from handwritten notes — running live on the web as the unmodified compiled binary.
▶ open the site · run the machine · play the game
C++17 · WebAssembly · no date libraries · GitHub Pages
Every year has a "doomsday" — a weekday that a known set of easy dates all fall on. Once you know that weekday, any date in the year is a short hop away.
1. Century anchor. Anchors cycle over 400 years: 1800s → Friday, 1900s → Wednesday, 2000s → Tuesday, 2100s → Sunday. The code derives this from a 2000 = Tuesday base instead of hardcoding a table.
2. Year's doomsday. For the last two digits y of the year:
doomsday = anchor + (y / 12) + (y % 12) + ((y % 12) / 4) (mod 7)
3. Month's anchor date. Each month has a date guaranteed to land on the doomsday:
| Month | Doomsday | Month | Doomsday |
|---|---|---|---|
| Jan | 3rd (4th in leap years) | Jul | 11th |
| Feb | 28th (29th in leap years) | Aug | 8th |
| Mar | 14th ("Pi day") | Sep | 5th |
| Apr | 4th | Oct | 10th |
| May | 9th | Nov | 7th |
| Jun | 6th | Dec | 12th |
The even months are 4/4, 6/6, 8/8, 10/10, 12/12; the odd ones pair up as 5/9, 9/5, 7/11, 11/7.
4. Step to the target. (day − month_anchor) mod 7, added to the year's doomsday, gives the weekday.
Three pages, zero frameworks, no backend — everything is static on GitHub Pages:
| Page | What it does |
|---|---|
| learn | The four steps above, a worked example, and the videos that taught me the technique |
| terminal | doomsday.cpp compiled byte-for-byte unmodified to WebAssembly, driving a fake VS Code terminal — shell prompt, typing effect with typos and backspaces, blinking block cursor. Button-controlled, so it works on phones too |
| game | Race the clock: random dates, four difficulty tiers up to brutal (any valid date in years 1–9999, biased toward century traps and leap-year Jan/Feb). Speed bonuses, streak multipliers, hints, achievements, a daily challenge — and exponentially growing penalties if you shotgun guesses. Scores live in your browser (localStorage) |
The game checks answers with an independent weekday oracle (docs/js/oracle.js), verified against 16,000+ dates from Python's datetime — the C++ stays pure, the answer key stays honest.
doomsday.cpp is the finished version. The other two .cpp files are earlier attempts at writing it from scratch, kept in the order they were written.
| File | What it is |
|---|---|
doomsday.cpp |
The final, working version. Prints the century anchor, the month's doomsday, and the year's doomsday as it goes, so you can follow the algorithm step by step |
attempt2.cpp |
Second attempt — single pass through the steps, logic sketched out as commented-out function blocks. Gets the doomsday right but stops short of naming the weekday correctly |
attempt1.cpp |
First attempt — reads all three inputs up front in a validation loop. The final step subtracts in the wrong direction, so its answers are off |
doomsday-walkthrough.ipynb |
The algorithm worked out cell by cell in a Cling C++17 notebook |
scratch.ipynb |
Scratch pad: modular arithmetic experiments (Cling C++14) |
notes-scan.pdf |
Handwritten notes the implementation was derived from |
resources.md |
Videos and a practice game for learning the technique |
docs/ |
The website (served by GitHub Pages from this folder) |
tools/build-wasm.sh |
Reproducible build: doomsday.cpp → WebAssembly, no source changes |
Native:
g++ doomsday.cpp -o doomsday
./doomsdayIt asks for the year, then the month, then the day, and prints the weekday along with each intermediate result.
Gregorian calendar only — negative years are rejected.
Web (already built and committed — only needed if you change the C++):
sh tools/build-wasm.sh # requires emsdkThe .ipynb files need a C++ Jupyter kernel (xeus-cling or Cling), not a Python one. doomsday-walkthrough.ipynb targets cling-cpp17, scratch.ipynb targets cling-cpp14.