This repo contains my solutions for Advent of Code. Each solution includes a short write-up explaining my approach.
So far I've only done 2024, in Zig. I might do other years in other languages later, or I might not.
Also see the accompanying blog post.
Each day links to the source code and the accompanying write-up.
Day | Title | Solution | Write up | Benchmark (ReleaseFast, µs) |
---|---|---|---|---|
1 | Historian Hysteria | Code | Write up | 41.8 |
2 | Red-Nosed Reports | Code | Write up | 54.4 |
3 | Mull it Over | Code | Write up | 23.2 |
4 | Ceres Search | Code | Write up | 5.9 |
5 | Print Queue | Code | Write up | 26.9 |
6 | Guard Gallivant | Code | Write up | 24,370.7 |
7 | Bridge Repair | Code | Write up | 10,014.7 |
8 | Resonant Collinearity | Code | Write up | 19.4 |
9 | Disk Fragmenter | Code | Write up | 151.7 |
10 | Hoof It | Code | Write up | 59.9 |
11 | Plutonian Pebbles | Code | Write up | 2,159.1 |
12 | Garden Groups | Code | Write up | 420.3 |
13 | Claw Contraption | Code | Write up | 14.7 |
14 | Restroom Redoubt | Code | Write up | 13.7 |
15 | Warehouse Woes | Code | Write up | 701.5 |
16 | Reindeer Maze | Code | Write up | 11,504.1 |
17 | Chronospatial Computer | Code | Write up | 44.8 |
18 | RAM Run | Code | Write up | 85.2 |
19 | Linen Layout | Code | Write up | 23,810.2 |
20 | Race Condition | Code | Write up | 157.4 |
21 | Keypad Conundrum | Code | Write up | 24.2 |
22 | Monkey Market | Code | Write up | 11,248.4 |
23 | LAN Party | Code | Write up | 38.2 |
24 | Crossed Wires | Code | Write up | 60.7 |
25 | Code Chronicle | Code | Write up | 24.9 |
Benchmarks are done on a Apple M3 Pro using this bash script. Each puzzle has separate measurements for parsing, part 1, and part 2.
Total runtime: 1,242.9 ms.
Benchmarks
Day | Title | Parsing (µs) | Part 1 (µs) | Part 2 (µs) | Total (µs) |
---|---|---|---|---|---|
1 | Historian Hysteria | 361.4 | 256.9 | 8.1 | 626.4 |
2 | Red-Nosed Reports | 598.2 | 33.8 | 91.2 | 723.2 |
3 | Mull it Over | 0.0 | 110.3 | 119.7 | 230.1 |
4 | Ceres Search | 67.7 | 4,849.7 | 1,093.7 | 6,011.2 |
5 | Print Queue | 361.5 | 8.8 | 95.1 | 465.4 |
6 | Guard Gallivant | 124.8 | 77.3 | 104,955.0 | 105,157.1 |
7 | Bridge Repair | 730.0 | 2,921.5 | 140,020.8 | 143,672.3 |
8 | Resonant Collinearity | 54.2 | 90.3 | 383.5 | 528.0 |
9 | Disk Fragmenter | 49.1 | 125.1 | 1,434.8 | 1,609.1 |
10 | Hoof It | 25.1 | 409.9 | 252.0 | 686.9 |
11 | Plutonian Pebbles | 1.0 | 933.6 | 32,657.6 | 33,592.2 |
12 | Garden Groups | 67.6 | 1,224.6 | 1,794.9 | 3,087.2 |
13 | Claw Contraption | 256.6 | 7.1 | 7.1 | 270.8 |
14 | Restroom Redoubt | 247.0 | 9.9 | 114,785.9 | 115,042.7 |
15 | Warehouse Woes | 311.0 | 634.5 | 1,103.9 | 2,049.4 |
16 | Reindeer Maze | 153.9 | 15,397.6 | 48,751.2 | 64,302.7 |
17 | Chronospatial Computer | 1.6 | 1.2 | 290.5 | 293.3 |
18 | RAM Run | 592.9 | 326.8 | 437.6 | 1,357.3 |
19 | Linen Layout | 127.0 | 207,814.8 | 207,684.8 | 415,626.6 |
20 | Race Condition | 325.1 | 2,164.6 | 93,134.5 | 95,624.2 |
21 | Keypad Conundrum | 0.7 | 41.4 | 566.2 | 608.2 |
22 | Monkey Market | 319.0 | 79,065.1 | 168,422.9 | 247,807.0 |
23 | LAN Party | 143.4 | 523.9 | 11.4 | 678.7 |
24 | Crossed Wires | 79.3 | 1,615.4 | 262.1 | 1,956.9 |
25 | Code Chronicle | 696.7 | 189.1 | 0.0 | 885.9 |
Total runtime: 146.1 ms.
Benchmarks
Day | Title | Parsing (µs) | Part 1 (µs) | Part 2 (µs) | Total (µs) |
---|---|---|---|---|---|
1 | Historian Hysteria | 24.5 | 18.5 | 2.9 | 46.0 |
2 | Red-Nosed Reports | 55.4 | 4.5 | 15.5 | 75.4 |
3 | Mull it Over | 0.0 | 9.4 | 14.2 | 23.6 |
4 | Ceres Search | 6.7 | 41.8 | 21.4 | 69.9 |
5 | Print Queue | 22.5 | 1.2 | 6.0 | 29.7 |
6 | Guard Gallivant | 20.2 | 12.3 | 13,156.5 | 13,189.0 |
7 | Bridge Repair | 67.4 | 437.4 | 12,760.7 | 13,265.5 |
8 | Resonant Collinearity | 3.3 | 4.5 | 18.5 | 26.3 |
9 | Disk Fragmenter | 6.8 | 25.4 | 234.3 | 266.5 |
10 | Hoof It | 3.4 | 42.7 | 37.7 | 83.8 |
11 | Plutonian Pebbles | 0.1 | 47.8 | 2,548.1 | 2,596.1 |
12 | Garden Groups | 6.9 | 258.1 | 368.4 | 633.5 |
13 | Claw Contraption | 18.8 | 0.9 | 0.9 | 20.5 |
14 | Restroom Redoubt | 15.2 | 2.0 | 20,863.8 | 20,881.1 |
15 | Warehouse Woes | 77.5 | 212.3 | 461.0 | 750.7 |
16 | Reindeer Maze | 49.2 | 4,676.7 | 15,408.5 | 20,134.4 |
17 | Chronospatial Computer | 0.1 | 0.2 | 42.0 | 42.3 |
18 | RAM Run | 43.3 | 23.5 | 62.6 | 129.4 |
19 | Linen Layout | 11.4 | 12,983.8 | 12,979.9 | 25,975.1 |
20 | Race Condition | 56.0 | 427.5 | 25,316.8 | 25,800.4 |
21 | Keypad Conundrum | 0.1 | 2.7 | 33.0 | 35.7 |
22 | Monkey Market | 22.7 | 5,660.8 | 16,055.8 | 21,739.4 |
23 | LAN Party | 16.6 | 25.3 | 2.6 | 44.5 |
24 | Crossed Wires | 8.4 | 91.7 | 16.8 | 116.9 |
25 | Code Chronicle | 45.2 | 66.8 | 0.0 | 112.1 |
Total runtime: 85.1 ms.
Benchmarks
Day | Title | Parsing (µs) | Part 1 (µs) | Part 2 (µs) | Total (µs) |
---|---|---|---|---|---|
1 | Historian Hysteria | 23.5 | 15.5 | 2.8 | 41.8 |
2 | Red-Nosed Reports | 42.9 | 0.0 | 11.5 | 54.4 |
3 | Mull it Over | 0.0 | 7.2 | 16.0 | 23.2 |
4 | Ceres Search | 5.9 | 0.0 | 0.0 | 5.9 |
5 | Print Queue | 22.3 | 0.0 | 4.6 | 26.9 |
6 | Guard Gallivant | 14.0 | 25.2 | 24,331.5 | 24,370.7 |
7 | Bridge Repair | 72.6 | 321.4 | 9,620.7 | 10,014.7 |
8 | Resonant Collinearity | 2.7 | 3.3 | 13.4 | 19.4 |
9 | Disk Fragmenter | 0.8 | 12.9 | 137.9 | 151.7 |
10 | Hoof It | 2.2 | 29.9 | 27.8 | 59.9 |
11 | Plutonian Pebbles | 0.1 | 43.8 | 2,115.2 | 2,159.1 |
12 | Garden Groups | 6.8 | 164.4 | 249.0 | 420.3 |
13 | Claw Contraption | 14.7 | 0.0 | 0.0 | 14.7 |
14 | Restroom Redoubt | 13.7 | 0.0 | 0.0 | 13.7 |
15 | Warehouse Woes | 14.6 | 228.5 | 458.3 | 701.5 |
16 | Reindeer Maze | 12.6 | 2,480.8 | 9,010.7 | 11,504.1 |
17 | Chronospatial Computer | 0.1 | 0.2 | 44.5 | 44.8 |
18 | RAM Run | 35.6 | 15.8 | 33.8 | 85.2 |
19 | Linen Layout | 10.7 | 11,890.8 | 11,908.7 | 23,810.2 |
20 | Race Condition | 48.7 | 54.5 | 54.2 | 157.4 |
21 | Keypad Conundrum | 0.0 | 1.7 | 22.4 | 24.2 |
22 | Monkey Market | 20.7 | 0.0 | 11,227.7 | 11,248.4 |
23 | LAN Party | 13.6 | 22.0 | 2.5 | 38.2 |
24 | Crossed Wires | 5.0 | 41.3 | 14.3 | 60.7 |
25 | Code Chronicle | 24.9 | 0.0 | 0.0 | 24.9 |
Total runtime: 139.35 ms.
Benchmarks
Day | Title | Parsing (µs) | Part 1 (µs) | Part 2 (µs) | Total (µs) |
---|---|---|---|---|---|
1 | Historian Hysteria | 30.1 | 17.8 | 2.6 | 50.6 |
2 | Red-Nosed Reports | 59.2 | 3.3 | 14.4 | 76.8 |
3 | Mull it Over | 0.0 | 15.4 | 20.7 | 36.1 |
4 | Ceres Search | 6.8 | 634.8 | 118.4 | 760.0 |
5 | Print Queue | 30.5 | 1.0 | 6.1 | 37.5 |
6 | Guard Gallivant | 14.8 | 34.1 | 26,542.4 | 26,591.4 |
7 | Bridge Repair | 93.2 | 886.4 | 26,021.9 | 27,001.5 |
8 | Resonant Collinearity | 4.5 | 6.7 | 28.2 | 39.3 |
9 | Disk Fragmenter | 6.2 | 15.6 | 149.0 | 170.8 |
10 | Hoof It | 3.0 | 51.9 | 37.7 | 92.6 |
11 | Plutonian Pebbles | 0.1 | 68.2 | 2,797.4 | 2,865.7 |
12 | Garden Groups | 7.8 | 189.2 | 252.5 | 449.4 |
13 | Claw Contraption | 20.5 | 0.0 | 0.0 | 20.5 |
14 | Restroom Redoubt | 39.1 | 0.1 | 1,358.3 | 1,397.5 |
15 | Warehouse Woes | 16.6 | 257.4 | 503.1 | 777.1 |
16 | Reindeer Maze | 46.9 | 2,665.8 | 9,338.2 | 12,050.9 |
17 | Chronospatial Computer | 0.2 | 0.3 | 69.1 | 69.6 |
18 | RAM Run | 71.7 | 25.2 | 43.0 | 139.9 |
19 | Linen Layout | 21.8 | 25,477.8 | 25,483.3 | 50,982.9 |
20 | Race Condition | 60.2 | 65.2 | 66.2 | 191.7 |
21 | Keypad Conundrum | 0.1 | 2.1 | 27.9 | 30.1 |
22 | Monkey Market | 23.6 | 0.0 | 15,141.3 | 15,164.8 |
23 | LAN Party | 11.2 | 42.8 | 2.6 | 56.6 |
24 | Crossed Wires | 10.4 | 204.6 | 23.2 | 238.1 |
25 | Code Chronicle | 60.3 | 0.0 | 0.0 | 60.4 |
To make things a little more interesting, I set a few constraints and rules for myself:
- The code must be readable. By "readable", I mean the code should be straightforward and easy to follow. No unnecessary abstractions. I should be able to come back to the code months later and still understand (most of) it.
- Solutions must be a single file. No external dependencies. No shared utilities module. Everything needed to solve the puzzle should be visible in that one solution file.
- The total runtime must be under one second. All solutions when run sequentially should finish in under one second. I want to improve my performance engineering skills.
- Parts should be solved separately. This means: (1) no solving both parts simultaneously, and (2) no doing extra work in part one that make part two faster. The aim of this is to get a clear idea of how long each part takes on its own.
- No concurrency or parallelism. Solutions must run sequentially on a single thread. This keeps the focus on the efficiency of the algorithm. I can't speed up slow solutions by using multiple CPU cores.
- No ChatGPT. No Claude. No AI help. I want to train myself, not the LLM. I can look at other people's solutions, but only after I have given my best effort at solving the problem.
- Follow the constraints of the input file. The solution doesn't have to work for all possible scenarios, but it should work for all other inputs; if the input file only contains 8-bit unsigned integers, it doesn't have to handle larger integer types.
- Hardcoding is allowed.
For example: size of the input, number of rows and columns, etc. Since the input is known at compile-time, we can skip runtime parsing and just embed it into the program using Zig's
@embedFile
.
To run the solutions, you'll first need to place your input files in the src/days/data/
directory with the format dayXX.txt
(add leading zeros for days 1-9). This project uses the Zig build system to run the commands.
Below are a list of the available commands. For the run and bench steps, you can also pass the optimize mode with the -Doptimize
flag.
zig build
- Builds all of the binaries. This is useful if you just want to compile without running the programs.
zig build run
- Runs all solution sequentially.zig build run -Day=XX
- Runs the solution for a single day.
zig build bench
- Benchmarks all solutions sequentially.zig build bench -Day=XX
- Benchmarks the solution for a single day.
zig build test
- Tests all solutions sequentially.zig build test -Day=XX
- Tests the solution for a single day.