Advent of Code 2023 was a strong year for cj81499, with 20 days fully completed (both parts), one day with only Part 1 solved (Day 23 — A Long Walk), and another with only Part 1 (Day 25 — Snowverload). Days 20–22 remain unsolved. The puzzles span a rich variety of problem types: range-interval algebra, pipe-grid flood-fill, hand-ranking card games, polynomial extrapolation, and constraint-solving with an SMT solver.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/cj81499/advent-of-code/llms.txt
Use this file to discover all available pages before exploring further.
Puzzle inputs are personal and are not included in the repository. To run
these solutions you will need to supply your own input, for example via
aocd. See
Solution Structure for how the project is organised.
Progress Table
| Day | Title | Part 1 | Part 2 | Tests |
|---|---|---|---|---|
| 01 | Trebuchet?! | ⭐ | ⭐ | ✅ |
| 02 | Cube Conundrum | ⭐ | ⭐ | ✅ |
| 03 | Gear Ratios | ⭐ | ⭐ | ✅ |
| 04 | Scratchcards | ⭐ | ⭐ | ✅ |
| 05 | If You Give A Seed A Fertilizer | ⭐ | ⭐ | ✅ |
| 06 | Wait For It | ⭐ | ⭐ | ✅ |
| 07 | Camel Cards | ⭐ | ⭐ | ✅ |
| 08 | Haunted Wasteland | ⭐ | ⭐ | ✅ |
| 09 | Mirage Maintenance | ⭐ | ⭐ | ✅ |
| 10 | Pipe Maze | ⭐ | ⭐ | ✅ |
| 11 | Cosmic Expansion | ⭐ | ⭐ | ✅ |
| 12 | Hot Springs | ⭐ | ⭐ | ✅ |
| 13 | Point of Incidence | ⭐ | ⭐ | ✅ |
| 14 | Parabolic Reflector Dish | ⭐ | ⭐ | ✅ |
| 15 | Lens Library | ⭐ | ⭐ | ✅ |
| 16 | The Floor Will Be Lava | ⭐ | ⭐ | ✅ |
| 17 | Clumsy Crucible | ⭐ | ⭐ | ✅ |
| 18 | Lavaduct Lagoon | ⭐ | ⭐ | ✅ |
| 19 | Aplenty | ⭐ | ⭐ | ✅ |
| 20 | ? | ❓ | ❓ | ❓ |
| 21 | ? | ❓ | ❓ | ❓ |
| 22 | ? | ❓ | ❓ | ❓ |
| 23 | A Long Walk | ⭐ | ❓ | ✅ |
| 24 | Never Tell Me The Odds | ⭐ | ⭐ | ✅ |
| 25 | Snowverload | ⭐ | ✗ | ✅ |
Notable Solutions
Day 5 — If You Give A Seed A Fertilizer
Part 1 maps individual seed numbers through a chain of almanac maps. Each map is a list ofMappingRange entries described by a destination range start,
source range start, and length. A value falls through unchanged when no range
covers it.
Part 2 reinterprets the seed list as (start, length) pairs, producing
millions of seeds — too many to enumerate directly. The solution instead
propagates ranges through each map layer. For every input range it finds the
intersection with each MappingRange, converts the overlapping sub-range
wholesale by offsetting it, and queues the non-overlapping remainders (computed
with a range_difference helper) for further matching within the same map
layer. This keeps the working set to a handful of range objects regardless of
how large the seed spans are, reducing an overnight brute-force into a
millisecond interval sweep.
Day 10 — Pipe Maze
Part 1 locates the single closed loop of pipe tiles starting fromS using
a straightforward BFS that respects each pipe character’s connection directions
(|, -, L, J, 7, F). The answer is the maximum BFS distance —
i.e. the point farthest from the start along the loop.
Part 2 counts tiles enclosed by the loop. Rather than ray-casting through
grid cells (which breaks at corner sequences), the solution floods the corners
of grid cells — the lattice points between tiles. Starting from the top-left
corner of (0, 0), a BFS propagates through corners, but can only cross between
two adjacent loop tiles if those tiles are not connected to each other (the
can_flood check). After flooding, any grid cell whose four corners were all
unreachable by the flood is interior to the loop. This elegantly handles all
pipe-corner ambiguities without special-casing.
Day 24 — Never Tell Me The Odds
Part 1 intersects hailstone trajectories in the XY-plane analytically. Each hailstone’s path is converted to slope-intercept form (y = mx + b), then
pairs of hailstones are checked for a forward-time intersection within the
specified bounding box.
Part 2 asks for the starting position and velocity of a rock that collides
with every hailstone. This is an underdetermined-looking system, but with
enough hailstones it is fully determined. The solution uses the
z3 SMT solver: it declares six real-valued
unknowns (px, py, pz, vx, vy, vz) and, for each hailstone, adds a collision
constraint parameterised by a per-hailstone time variable t. Three hailstones
are sufficient to fix the solution; z3 returns the unique satisfying model and
the answer is px + py + pz.