Advent of Code 2024 - Day 25: Code Chronicle
1 2 3 4 5 6 7 8 9 10 11 12 |
from advent import parse, partition, cross_product pairs = [ (schematic[0][0] == '#', [ len(partition(line, lambda c: c == line[0])[0]) for line in schematic ]) for schematic in parse(25, lambda s: list(zip(*str.split(s, '\n'))), sep='\n\n') ] locks = [ lengths for is_lock, lengths in pairs if is_lock ] keys = [ lengths for is_lock, lengths in pairs if not is_lock ] pins = 5 total = sum(1 for lock, key in cross_product(locks, keys) if all([ lock[pin] <= key[pin] for pin in range(pins) ])) assert total == 2618 |
Parsing
We’re given a list of schematics - either for locks or keys. For each schematic, we’ll do the following:
Transpose the matrix (using zip(*...)
), so the pins are horizontal instead of vertical:
1 |
lambda s: list(zip(*str.split(s, '\n'))) |
Compute the length of the inital list of either .
characters or #
characters:
1 |
[ len(partition(line, lambda c: c == line[0])[0]) for line in schematic ] |
Finally, form a 2-tuple of (<boolean>, <len>)
where the <boolean>
indicates the schematic is a lock, and the <len>
is the length of the #
characters for locks or .
characters for keys:
1 |
(schematic[0][0] == '#', [ len(partition(line, lambda c: c == line[0])[0]) for line in schematic ]) |
Solution
For today, parsing the input is more than half the battle! Once we have our data structures in place via the above, we simply form a cartesian product of locks and keys, and filter the pairs by whether the key fits in the lock:
1 2 |
total = sum(1 for lock, key in cross_product(locks, keys) if all([ lock[pin] <= key[pin] for pin in range(pins) ])) |
Conclusion
This was a nice easy puzzle to wrap up Advent of Code 2024. I really enjoyed this years contest - it was a fun way to become more proficient with Python and some of its ecosystem - particularly the networkx
library.