Advent of Code 2025 - Day 8: Playground
Day 8 was brutal. Not because the algorithm is complex - but because I kept making implementation mistakes that cost hours of debugging.
The Problem
Given 3D coordinates of junction boxes, connect them with light strings. Connect the closest pairs first, forming circuits. After making a certain number of connections, find the sizes of the three largest circuits.
This is essentially asking: perform a greedy connection strategy (always connect the two closest unconnected boxes) and track which connected components (circuits) form.
Part 1: Connect 1000 Pairs
After 1000 connections, multiply the sizes of the three largest circuits.
Mistake 1: Single Loop Instead of Double Loop
My first attempt calculated distances wrong:
|
|
This only compared consecutive boxes. I needed to compare every pair:
|
|
The heapq gives us the closest pairs in order. This is the greedy part - always connect the two closest boxes.
Mistake 2: Forgetting to Merge Circuits
This cost me hours. When connecting two boxes, there are four cases:
- Both in same circuit → Do nothing (already connected)
- Both in different circuits → Merge the two circuits
- One in circuit, one not → Add the solo box to the circuit
- Neither in circuit → Create new circuit with both
I implemented case 3 and case 4, but forgot case 2. My circuits never merged, so I never got large circuits.
The fix:
|
|
Mistake 3: Forgetting to Remove Merged Circuit
After merging circuits, I initially forgot junctions.remove(right_junction). This left duplicate circuits in the list, throwing off the count.
Sorting by Inner List Length
To find the three largest circuits, I needed to sort by circuit size. Lambda syntax reminder:
|
|
First try (after fixing all bugs).
Part 2: Connect Until One Circuit
Part 2 was straightforward after Part 1’s struggle. Instead of stopping after 1000 connections, keep connecting until all boxes are in one circuit.
The only changes:
|
|
The check len(junctions[0]) == len(lines) works because once all boxes are connected, there’s only one circuit remaining, and its size equals the total number of boxes.
Answer: multiply the X coordinates of the final connection.
What This Really Is
This is a Union-Find (Disjoint Set Union) problem disguised as circuit building.
My list-based approach works but is slower (O(n) to find which circuit contains a box). Union-Find with path compression is O(α(n)) ≈ O(1).
The Lesson
Part 1 took hours because of small bugs:
- Wrong loop structure (single vs double)
- Missing merge logic
- Forgetting to remove merged circuit
Part 2 took minutes because the logic was already there.
The real lesson: when something seems conceptually simple but won’t work, step through an example by hand. I would have caught the “circuits never merge” bug immediately if I’d traced through the example instead of staring at code.
Sixteen stars total. A humbling reminder that implementation details matter.