Advent of Code 2025 Day 6: Trash Compactor
"""Advent of Code 2025: Day 6 - Trash Compactor"""
from advent import parse, atoms, operator, reduce, compose, Generator
def apply(op_sym: str, args: list[int]) -> int:
"""Apply an operator to a list of arguments. For example, apply('+', [1,2,3]) returns 6."""
return reduce({'+': operator.add, '*': operator.mul}[op_sym], args)
def part1() -> int:
"""
1. Parse the input into rows
2. Transpose rows to columns using zip(*rows)
3. Sum the result of applying the operator to the args for each column"""
return sum([apply(col[-1], col[:-1]) for col in zip(*parse(6, atoms))])
def part2() -> int:
"""
1. Transform our input so columns become rows after reversing each line, and
forming the transpose. Then filter out any rows containing only spaces:
[[ '1', '2', '3', ' ', ' ', '6' ], [[ '6', '8', ' '],
[ '4', '5', ' ', ' ', '7', '8' ], --> [ ' ', '7', '*'], 68 * 7
[ '+', ' ', ' ', ' ', '*', ' ' ]] [ '3', ' ', ' '],
[ '2', '5', ' '],
[ '1', '4', '+']] 3 + 25 + 14
2. Return the sum of all answers generated by our helper function.
"""
rows = filter(
lambda row: ''.join(row).strip(),
zip(*parse(6, compose(reversed, list), do_rstrip=False)),
)
def answers(rows, args: list[int] = []) -> Generator[int, None, None]:
"""Accumulate an int argument from each row, until a row ends with an operator, then apply
the operator to the accumulated args, yield the answer, clear the arg list, and repeat."""
for row in rows:
args.append(int(''.join(row[:-1]).strip()))
if row[-1] in ['+', '*']:
yield apply(row[-1], args)
args = []
return sum(answers(rows))
assert part1() == 3525371263915
assert part2() == 6846480843636
Input Parsing
Parsing is a big part of today's puzzles! Consider our sample input:
For part 1, I'd like to have the following structure:
This is accomplished by transposing the matrix with : zip(*parse(6, atoms))
For part 2, I'd like to have the following structure:
But I'll settle for the following :)
[ (' ', ' ', '4', ' '),
('4', '3', '1', ' '),
('6', '2', '3', '+'),
(' ', ' ', ' ', ' '),
('1', '7', '5', ' '),
('5', '8', '1', ' '),
(' ', '3', '2', '*'),
(' ', ' ', ' ', ' '),
('8', ' ', ' ', ' '),
('2', '4', '8', ' '),
('3', '6', '9', '+'),
(' ', ' ', ' ', ' '),
('3', '5', '6', ' '),
('2', '4', ' ', ' '),
('1', ' ', ' ', '*') ]
This is accomplished by transposing the matrix, after we reverse the rows, with: zip(*parse(6, compose(reversed, list), do_rstrip=False)) I needed to add a do_rstrip argument to my parse function
because by default it strips spaces from the end of the file, and that removes crucial ending spaces!
Solution
For part 1, given the structure provided by our parsing, I just need to evaluate each tuple in the list by applying the operator (the last element) to the arguments (all but the last element), and sum all the results together.
For part 2, I have a little more work to do still. First, filter out the tuples containing only spaces,
since they're meaningless now.
I created a generator helper function to yield all the answers we need to sum up. For each row, it converts the tuple of
digit strings into an integer, and accumulates them in a list. If the tuple ends in an operator, we
apply the operator to the accumulated args, yield the answer, clear the arg list, and repeat until we're done.
