Skip to main content

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.

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.
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

DayTitlePart 1Part 2Tests
01Trebuchet?!
02Cube Conundrum
03Gear Ratios
04Scratchcards
05If You Give A Seed A Fertilizer
06Wait For It
07Camel Cards
08Haunted Wasteland
09Mirage Maintenance
10Pipe Maze
11Cosmic Expansion
12Hot Springs
13Point of Incidence
14Parabolic Reflector Dish
15Lens Library
16The Floor Will Be Lava
17Clumsy Crucible
18Lavaduct Lagoon
19Aplenty
20?
21?
22?
23A Long Walk
24Never Tell Me The Odds
25Snowverload

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 of MappingRange 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 from S 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.

Build docs developers (and LLMs) love