package main import ( "fmt" "os" "slices" "strconv" "strings" "github.com/dominikbraun/graph" ) func readLines(filename string) []string { raw, err := os.ReadFile(filename) if err != nil { panic(err) } return strings.Split(string(raw), "\n") } // input1 80446 func main() { filename := "input0.txt" if len(os.Args) > 1 { filename = os.Args[1] } lines := readLines(filename) p := parsePlayground(lines) circuits, err := p.wireClosest(1000) if err != nil { panic(err) } counts := map[uint]uint{} for _, circuit := range circuits { counts[circuit]++ } totals := []uint{} for _, v := range counts { totals = append(totals, v) } slices.Sort(totals) slices.Reverse(totals) fmt.Printf("%v\n", totals[0]*totals[1]*totals[2]) } func parsePlayground(lines []string) playground { p := playground{ boxes: []box{}, distances: graph.New(boxHash, graph.Weighted()), } for _, line := range lines { parts := strings.Split(line, ",") b := box{line: line} b.x, _ = strconv.Atoi(parts[0]) b.y, _ = strconv.Atoi(parts[1]) b.z, _ = strconv.Atoi(parts[2]) _ = p.distances.AddVertex(b) for _, c := range p.boxes { _ = p.distances.AddEdge(b.line, c.line, graph.EdgeWeight(b.distanceTo(c))) } p.boxes = append(p.boxes, b) } return p } func (p *playground) wireClosest(n uint64) (map[string]uint, error) { edges, err := p.distances.Edges() if err != nil { return nil, err } slices.SortFunc(edges, func(e1, e2 graph.Edge[string]) int { return e1.Properties.Weight - e2.Properties.Weight }) nextCircuit := uint(1) circuits := map[string]uint{} for i := range n { edge := edges[i] sourceCircuit := circuits[edge.Source] targetCircuit := circuits[edge.Target] if sourceCircuit == 0 && targetCircuit == 0 { circuits[edge.Source] = nextCircuit circuits[edge.Target] = nextCircuit nextCircuit++ continue } if sourceCircuit == 0 { circuits[edge.Source] = targetCircuit continue } if targetCircuit == 0 { circuits[edge.Target] = sourceCircuit continue } if sourceCircuit == targetCircuit { continue } for k, v := range circuits { if v == targetCircuit { circuits[k] = sourceCircuit } } } return circuits, nil } type playground struct { boxes []box distances graph.Graph[string, box] } func boxHash(b box) string { return b.line } type box struct { line string x int y int z int } func (b box) distanceTo(c box) int { x := c.x - b.x y := c.y - b.y z := c.z - b.z // no need to sqrt since we only care about relative distances return x*x + y*y + z*z }