Advent of Code 2025 Day 8

Author

Nathan Moore

— Day 8: Playground —

Connect the junction boxes so that we can light up the playground.

Your list contains many junction boxes; connect together the 1000 pairs of junction boxes which are closest together. Afterward, what do you get if you multiply together the sizes of the three largest circuits?

import math 
import numpy as np

with open('data-2025-08.txt', 'r') as f:
    inp = f.read().splitlines()

box = [list(map(int, i.split(','))) for i in inp]

len(box) # 1000
1000

I think I want to go through and calculate all the distances, just do that once, but I need to record them nicely. Then I need to create some groups and record them and be able to add junction boxes to them.

dist_array = np.full((1000,1000), 999999)

for b in range(1000): 
    for c in range(1000): 
        if b > c: 
            # only strictly greater, want to make half a matrix
            dist_array[b,c] = math.dist(box[b], box[c])

testing

np.min(dist_array)   

f = np.where(dist_array == np.min(dist_array))

f

box[f[0][0]]
box[f[1][0]]
[1757, 33995, 68141]

OK, I think I can just store the index of the junction box, not the coordinates. A list of lists to store the groups? Then I have to search each time I want to add something, but hopefully that’s not too bad. Or I can store the group that something is in against the original list.

[[x,y,z,g],[x,y,z],[x,y,z,g],...]

But then I’d have to go and collect those afterwards, which is probably quicker than searching each time.

Review: I need to combine groups, not just compare them. Then I need to adjust all the other members of that group!

grp = 1

for r in range(1000): 
    # find the minimum 1000 distances
    # np.min(dist_array)
    f = np.where(dist_array == np.min(dist_array))
    g = f[0][0]
    h = f[1][0]
    dist_array[g,h] = 999999
    
    if len(box[g]) == 3 and len(box[h]) == 3: 
        # there are no groups assigned to these boxes
        # assign a new group to each
        box[g].append(grp)
        box[h].append(grp)
        grp += 1
    elif len(box[g]) == 4 and len(box[h]) == 4: 
        # they are already assigned a group
        if box[g][3] != box[h][3]:
            # box[g], box[h]
            # combine the groups
            new = min(box[g][3], box[h][3])
            old = max(box[g][3], box[h][3])
            # new, old
            for c in box: 
                if len(c) == 4 and c[3] == old: 
                    c[3] = new

    elif len(box[g]) == 4 and len(box[h]) == 3:
        # assign g to h
        box[h].append(box[g][3])
    elif len(box[g]) == 3 and len(box[h]) == 4:
        # assign h to g
        box[g].append(box[h][3])
    else: 
        print('do not think we should get here')

Check the things

from collections import Counter

cc = {}

for b in box: 
    if len(b) > 3:
        # print(b)
        if b[3] in cc.keys(): 
            cc[b[3]] += 1
        else: 
            cc[b[3]] = 1
            
    
ccc = Counter(cc)

ccc.most_common(3)

94 * 69 * 51
330786

— Part Two —

Continue connecting the closest unconnected pairs of junction boxes together until they’re all in the same circuit. What do you get if you multiply together the X coordinates of the last two junction boxes you need to connect?

What’s my stopping condition? When the length reaches 1000? I don’t want to do Counter every time through. Let’s go big and try 10,000 instead of 1,000 and see what the groups look like.

Paste everything here so I can just run one cell

Thoughts: there is a point where every junction box is in a group, but we have a while to go until we have all the boxes in one group.

Except! if we run 5000 times, just by guessing, we find one group of 998 boxes - but we’re going to keep adding closer ones for a while, until we add those last two.

Print everything that happens after 5000? Yeah! Maybe.

box = [list(map(int, i.split(','))) for i in inp]

dist_array = np.full((1000,1000), 999999)

for b in range(1000): 
    for c in range(1000): 
        if b > c: 
            # only strictly greater, want to make half a matrix
            dist_array[b,c] = math.dist(box[b], box[c])

grp = 1

for r in range(10000): 
    # find the minimum 1000 distances
    # np.min(dist_array)
    f = np.where(dist_array == np.min(dist_array))
    g = f[0][0]
    h = f[1][0]
    dist_array[g,h] = 999999
    
    if r >= 5000 and (len(box[g]) == 3 or len(box[h]) == 3): 
        box[g], box[h]
    
    if len(box[g]) == 3 and len(box[h]) == 3: 
        # there are no groups assigned to these boxes
        # assign a new group to each
        box[g].append(grp)
        box[h].append(grp)
        grp += 1
    elif len(box[g]) == 4 and len(box[h]) == 4: 
        # they are already assigned a group
        if box[g][3] != box[h][3]:
            # box[g], box[h]
            # combine the groups
            new = min(box[g][3], box[h][3])
            old = max(box[g][3], box[h][3])
            # new, old
            for c in box: 
                if len(c) == 4 and c[3] == old: 
                    c[3] = new

    elif len(box[g]) == 4 and len(box[h]) == 3:
        # assign g to h
        box[h].append(box[g][3])
    elif len(box[g]) == 3 and len(box[h]) == 4:
        # assign h to g
        box[g].append(box[h][3])
    else: 
        print('do not think we should get here')



cc = {}

for b in box: 
    if len(b) > 3:
        # print(b)
        if b[3] in cc.keys(): 
            cc[b[3]] += 1
        else: 
            cc[b[3]] = 1
            
    
ccc = Counter(cc)

ccc.most_common(3)

# 1000  : original answer
# 10000 : all in one group
# 5000  : [(1, 998)]

# 51642 * 63448 = 3276581616
[(1, 1000)]