package main import ( "fmt" "math" "sort" "strings" "git.z1glr.de/advent-of-code-2025/pkg/aoc" ) type Node struct { X, Y, Z int root *Node Size int ID int } func (p *Node) DistanceTo(p2 *Node) float64 { return math.Sqrt(float64((p.X-p2.X)*(p.X-p2.X) + (p.Y-p2.Y)*(p.Y-p2.Y) + (p.Z-p2.Z)*(p.Z-p2.Z))) } func (p *Node) GetRoot() *Node { if p.root == nil { return p } else { root := p.root.GetRoot() p.root = root return root } } func PointFromString(s string) Node { parts := strings.Split(s, ",") return Node{ X: aoc.ParseInt(parts[0]), Y: aoc.ParseInt(parts[1]), Z: aoc.ParseInt(parts[2]), Size: 1, } } type Connection struct { Length float64 P1, P2 *Node } func do(test bool) (int, int) { rows := aoc.ReadFileRows(test) points := make([]Node, len(rows)) for ii, rr := range rows { points[ii] = PointFromString(rr) points[ii].ID = ii + 1 } connections := []Connection{} for ii := range points[:len(points)-1] { for jj := ii + 1; jj < len(points); jj++ { // for jj := range points[ii+1:] { p1 := &points[ii] p2 := &points[jj] // p2 := &points[ii+1+jj] connections = append(connections, Connection{ Length: p1.DistanceTo(p2), P1: p1, P2: p2, }) } } // sort distances by length sort.Slice(connections, func(i, j int) bool { return connections[i].Length < connections[j].Length }) if test { connections = connections[:10] } else { connections = connections[:1000] } for ii := range connections { cc := &connections[ii] root1 := cc.P1.GetRoot() root2 := cc.P2.GetRoot() if root1 != root2 { root2.root = root1 root1.Size += root2.Size } } roots := []*Node{} for ii := range points { pp := &points[ii] if pp.GetRoot() == pp { roots = append(roots, pp) } } sort.Slice(roots, func(i, j int) bool { return roots[i].Size > roots[j].Size }) res1 := roots[0].Size * roots[1].Size * roots[2].Size fmt.Println(res1) return res1, 0 } func main() { if r1, r2 := do(true); r1 == 40 && r2 == 0 { do(false) } }