no this isn't about alexandria ocasio-cortez
1package main
2
3import (
4 "cmp"
5 "fmt"
6 "math"
7 "slices"
8 "strconv"
9 "strings"
10
11 "tangled.org/evan.jarrett.net/aoc2025/internal/puzzle"
12)
13
14type Edge struct {
15 A Coord
16 B Coord
17 Distance float64
18}
19
20type Coord struct {
21 x int
22 y int
23 z int
24}
25
26func (c Coord) Distance(other Coord) float64 {
27 dx := float64(other.x - c.x)
28 dy := float64(other.y - c.y)
29 dz := float64(other.z - c.z)
30 return math.Sqrt(dx*dx + dy*dy + dz*dz)
31}
32
33func buildEdges(coords []Coord) []Edge {
34 var edges []Edge
35 for i := range coords {
36 for j := i + 1; j < len(coords); j++ {
37 edges = append(edges, Edge{
38 A: coords[i],
39 B: coords[j],
40 Distance: coords[i].Distance(coords[j]),
41 })
42 }
43 }
44 slices.SortFunc(edges, func(a, b Edge) int {
45 return cmp.Compare(a.Distance, b.Distance)
46 })
47 return edges
48}
49
50type DayEight struct {
51 coordinates []Coord
52 edges []Edge
53 numPairs int
54}
55
56func (d *DayEight) ParseInput(input string) error {
57 for line := range strings.SplitSeq(strings.TrimSpace(input), "\n") {
58 line = strings.TrimSpace(line)
59 if line == "" {
60 continue
61 }
62 parts := strings.Split(line, ",")
63 if len(parts) != 3 {
64 return fmt.Errorf("invalid input: %s", line)
65 }
66 x, _ := strconv.Atoi(parts[0])
67 y, _ := strconv.Atoi(parts[1])
68 z, _ := strconv.Atoi(parts[2])
69 d.coordinates = append(d.coordinates, Coord{
70 x: x,
71 y: y,
72 z: z,
73 })
74 }
75 d.edges = buildEdges(d.coordinates)
76
77 return nil
78}
79
80func (d *DayEight) Part1() (int, error) {
81 circuit := make(map[Coord]int)
82 for i, c := range d.coordinates {
83 circuit[c] = i
84 }
85
86 // Connect the numPairs shortest pairs
87 for i := 0; i < d.numPairs && i < len(d.edges); i++ {
88 circuitA := circuit[d.edges[i].A]
89 circuitB := circuit[d.edges[i].B]
90
91 if circuitA != circuitB {
92 for c := range circuit {
93 if circuit[c] == circuitB {
94 circuit[c] = circuitA
95 }
96 }
97 }
98 }
99
100 // Count sizes of each circuit
101 sizes := make(map[int]int)
102 for _, circuitID := range circuit {
103 sizes[circuitID]++
104 }
105
106 var sizeList []int
107 for _, s := range sizes {
108 sizeList = append(sizeList, s)
109 }
110 slices.Sort(sizeList)
111 slices.Reverse(sizeList)
112
113 return sizeList[0] * sizeList[1] * sizeList[2], nil
114}
115
116func (d *DayEight) Part2() (int, error) {
117 circuit := make(map[Coord]int)
118 for i, c := range d.coordinates {
119 circuit[c] = i
120 }
121
122 var finalA, finalB Coord
123
124 // loop through all edges until nothing left
125 for _, e := range d.edges {
126 circuitA := circuit[e.A]
127 circuitB := circuit[e.B]
128
129 if circuitA != circuitB {
130 for c := range circuit {
131 if circuit[c] == circuitB {
132 circuit[c] = circuitA
133 }
134 }
135 d.numPairs--
136 if d.numPairs == 1 {
137 finalA = e.A
138 finalB = e.B
139 }
140 }
141 }
142 fmt.Printf("Final coordinates: %v, %v\n", finalA, finalB)
143 return finalA.x * finalB.x, nil
144}
145
146func main() {
147 puzzle.Run(8, &DayEight{numPairs: 1000})
148}