Advent of Code 2025 - Day 8Playground
| Problem statement | Source code | Tags: Data structures
Part 1
First collect the distance between each pair of point (more precisely, squared distance to avoid floating point issues).
Now, the naïve way is to sort all edges by distance, which is .; but note that we don't need that many edges, so most of the ordering is useless. Turns out that on-demand sorting is possible with a heap. Heapifying a list is , and each pop is , so the total time is , which is much better than the previous approach. To make Rust's BinaryHeap work as a min-heap, we can wrap the values in Reverse.
Then we can connect each pair of points in order of distance. I could have used adjacency lists and BFS, which would have time , but since we are only interested in the number of components, I use a union-find data structure instead, which turns out to be very useful for part 2 as well. Theoretically, this should be , which is slightly worse than BFS, but in practice both are dwarfed by the distance calculation.
Finally I just get the top 3 sizes and multiply them together.
Part 2
I believe that the naïve solution is to run a BFS for every additional edge until we have only one component left. However, this is at least . Since I already have a union-find, this becomes much easier. I just keep track of the number of components, and stop when it reaches 1. I decrement the number of components every time I union two components together—when union() returns true.
By the way, initially I had a wrong solution, which was basically this:
However, this would break as soon as every component has size greater than 1, not when there is only one component left. I didn't even realize I was wrong before I started writing this writeup. I guess I just got lucky.