Advent of Code 2025
Racket notes and solutions
12/7/2025
Ongoing log
Newest entries up top; currently compacting cephalopod homework while dodging magnetically sealed trash doors.
Day 6: Trash Compactor (cephalopod math)
Columns are the operands, an all-space column is the delimiter, and the operator sits at the bottom. Part 1 reads the columns left-to-right; part 2 reads them right-to-left by evaluating the transposed columns in order.
Notes:
apply map listhandles the transpose once we assume rectangular input; no explicit grid structs needed.for/foldaccumulates column groups in one pass, treating all-space columns as delimiters.- Tokenizing stays declarative: strip spaces, digits -> numbers, operators via
string->symbol. digits->numberfolds whole columns of digits without concatenating strings;evalreuses the base namespace for the operators.
Day 5: fresh ingredient IDs
Split the input into ranges and available IDs. Merge overlapping/touching ranges into a normalized range-set, then use range-set-range-containing-or-absent for membership and in-range-set to sum total coverage.
Notes:
- Leaning on the Rebellion package:
rebellion/base/rangefor closed ranges andrebellion/collection/range-setfor normalized, non-overlapping sets. range-setrequires disjoint/touching ranges, so a small merge pass coalesces overlaps before building it; comparator defaults handle numeric ordering.- Freshness check uses
range-set-range-containing-or-absent, returning an option;present?is the clean predicate. in-range-setwalks the merged ranges; widths are inclusive (add1on hi - lo) to sum total coverage.
Day 4: forklift-accessible rolls
Count @ cells whose 8-neighbor count of @ is < 4. For part two, repeatedly remove the accessible rolls and re-count until none remain.
Notes:
- Uses vectors instead of lists to avoid
list-setrebuilding rows while iterating removals. - Helpers (
grid-cell,grid-width,grid-height) keep adjacency code short; assumes non-empty grid from AoC input. match-definedestructures direction tuples inline;count+curryreads like a predicate.- Coord-first
update-gridpairs withfoldlfor the peel-off step without mutation of the previous grid.
Day 3: emergency battery banks
Greedy scan: try digits 9→0, pick the leftmost one that leaves room for the remaining picks, then recurse on the suffix. Do it once for length 2 and once for length 12.
Notes:
- Greedy search resets the digit scan after each pick;
space?blocks choices that strand you short of k. index-ofreturns#fwhen a digit is absent, which cleanly skips to the next candidate.- Both parts share the same picker; the outer
for/listruns it for k=2 and k=12. - Threading macros (
~>>,~>) keep the parsing/pipeline readable;match-let/list*tidy destructuring without mutation. compose+currybuilds the mapper inline, highlighting the functional style.
Day 2: tandem repeats and periodicity
Looking for numbers that are mirror-tandems (two equal halves) and, separately, numbers whose digit strings are fully tiled by a shorter period.
Notes:
- Parsing stays regex-based; inclusive ranges expand the input spans.
tandem?is generic over k chunks; using 2 for the mirror test.periodic?delegates totandem?over divisors to detect full tiling.- Threading (
~>) andλ~>>keep transformations point-free;for*/sumwith#:whenclauses filters in-line. in-stream+in-listcomprehensions keep iteration lazy-ish and declarative.
Day 1: counting dial clicks
The dial starts at 50. Negative turns rotate left, positive turns rotate right, and the first part asks for how many times we land exactly on 0. The twist in part two counts every pass over 0 while spinning.
Notes to revisit later:
- Consider a more direct arithmetic expression for part two to avoid per-click iteration on large turns.
- Regex captures with
regexp-match*+#:match-select valuesto split direction/magnitude pairs. for/foldandfor/sumaccumulators with multi-value returns to carry state cleanly.in-inclusive-rangeto cover both the path and landing step when counting clicks.#:when/#:doclauses inside comprehensions to gate work without extra conditionals.- Pattern matching via
match-let*avoids manual indexing; pure arithmetic withmodulokeeps the state immutable between folds.