Eibhlín F. O'Dwyer

music | linguistics | fiction | gender | linux

Advent Of Code 2025, Day 6

python | aoc

December 08, 2025

This is the sixth in a series of blog posts about the 2025 Advent of Code. For previous entries in this thrilling series, see here. I didn’t get any time over the weekend to attempt this, so it’s now a game of catch-up.

The code is now up online and available for your reading pleasure! Check it out here.

Day 5: Trash Compactor

Advent of Code: Day 6

Part One

I’ve slipped down the rubbish chute and into the tip. The door is locked, but a friendly family of slugs offer to unlock the door if I help the youngest with their maths homework. It seems straightforward enough:

123 328  51 64
 45 64  387 23
  6 98  215 314
*   +   *   +

Perform the relevant operation (addition or multiplication only) on the column, and sum the overall totals for the correct answer. I didn’t struggle overmuch with this one,

#! /usr/bin/env python3
import math

def do_maths(operation,values: list):
    if operation == "+":
        return sum(values)
    if operation == "*":
        return math.prod(values)

with open("input.txt","r") as homework:
    content = homework.read().splitlines()
    hw = []
    for line in content:
        hw.append(line.split())
    operations = hw[-1]
    values = hw[:-1]

    count = 0

    for i in range(0,len(operations)):
        operands = []
        for v in range(0,len(values)):
            operands.append(int(values[v][i]))
        count += do_maths(operations[i],operands)

    print(count)

This was fiddly, and I’m learning that my line-by-line approach to writing code is not very efficient. But essentially we’re converting each row into a list, and then scanning left to right across all lists at the same time, and then performing each sum. Just the way a human would do it, really. It occurs to me on review, and after having completed part 2, that I could have gone about this in a much more programmatic way, generating the right variables in fewer lines of (admittedly more complex) code. Still, it gets the answer in 1/10th of a second:

time ./part_1.py
$REDACTED$
./part_1.py  0.01s user 0.00s system 94% cpu 0.016 total

Part 2

Oh no, slugs do maths differently to humans! They list the sums in columns from right-to-left, where the highest significant digit is at the top. So

64
23
314
+

Actually translates to 4 + 431 + 623 = 1058.

I was not remotely prepared for this, and I had not the slightest clue how to begin. I wasn’t able to figure out how to use the whitespace to my advantage, and all hope felt lost. I opted to go to the subreddit and look through some of the submitted answers to try and get a feel for the solution. I found this comment which makes use of the zip function, which I had not heard of before.

zip enables you to combine multiple lists (or other iterable objects) into one zipped unit. In this case, I was able to combine each column of the input into its own list, thanks to a nifty *, which essentially rotates the data (I think, I’m still hazy on the details).

Then it’s a matter of turning all that whitespace into useable information, here I convert each to a slash, and use double slashes to delimit where a number ends. Convert to integars and then perform the previous function to get the final answer:

#! /usr/bin/env python3
import math

def do_maths(operation,values: list):
    if operation == "+":
        return sum(values)
    if operation == "*":
        return math.prod(values)

with open("input.txt","r") as homework:
    # ::-1 means to go from right to left
    values = [list(line.strip('\n'))[::-1] for line in homework]

    # Get a list of the operations
    operations = ''.join(values[-1]).split()

    # Use zip to work on all the lists at once, with * rotating the data
    zipped_values = zip(*values[:-1])

    # Strip out the white space
    values_list = [''.join(z).strip() for z in zipped_values]

    # Split into lists for each sum
    values_list = [val.split("/") for val in "/".join(values_list).split("//")]

    # Ensure they're integars
    operands = [list(map(int, vals)) for vals in values_list]

    count = 0
    for i in range(0,len(operands)):
        count += do_maths(operations[i],operands[i])

    print(count)

This is one of the larger changes I’ve had to make in the course of this challenge between part one and two. I made some pretty silly mistakes initially, and timed out my ability to enter answers to the Advent of Code submission page for a while. I had the bright idea to store each range as an array of 2: the lower bound and the upper bound. Then from there, I could simply take the difference between the upper and lower bounds and it would work!

Reader, it did not work. I was stuck for a very long time. What I hadn’t appreciated was that there are ranges where the lower bound starts in the middle of another saved range. Completely useless to me, as I want the unique number. So I wrote up some logic to sort the ranges, and then go through one by one and amend the values according to neighbours. This still did not work, and I had to figure out a way to merge the ranges together.

This was not pretty, and it took me a long time to realise that the way I’d set up my loop meant that removing entries in the array would break the code before I could get the answer. Finally I hit on going backwards through the list of ranges, safe in the knowledge that removing a range wouldn’t break anything by deleting things that the program expected to check later on.

❯ time ./part_2.py
$REDACTED$
./part_2.py  0.02s user 0.00s system 96% cpu 0.027 total

Nice and quick again. I would have been absolutely sunk without /u/CDninja on Reddit, and would have definitely have had to have brute forced this had I not gone in search of clues!