From 019510f0b6cba78ac250fe8ef685de770ac145ce Mon Sep 17 00:00:00 2001 From: Mindaugas Bernotas Date: Mon, 8 Dec 2025 21:55:03 +0200 Subject: [PATCH] Solve day 8 --- day8/example.txt | 20 +++++ day8/main.go | 187 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 day8/example.txt create mode 100644 day8/main.go diff --git a/day8/example.txt b/day8/example.txt new file mode 100644 index 0000000..e98a3b6 --- /dev/null +++ b/day8/example.txt @@ -0,0 +1,20 @@ +162,817,812 +57,618,57 +906,360,560 +592,479,940 +352,342,300 +466,668,158 +542,29,236 +431,825,988 +739,650,466 +52,470,668 +216,146,977 +819,987,18 +117,168,530 +805,96,715 +346,949,466 +970,615,88 +941,993,340 +862,61,35 +984,92,344 +425,690,689 diff --git a/day8/main.go b/day8/main.go new file mode 100644 index 0000000..d53b227 --- /dev/null +++ b/day8/main.go @@ -0,0 +1,187 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "log" + "maps" + "math" + "os" + "slices" + "strconv" + "strings" + "time" +) + +func main() { + connections := flag.Int("connect", -1, "Number of connections to perform (-1 unlimited).") + debug := flag.Bool("debug", false, "Debug.") + flag.Parse() + + f := os.Stdin + if flag.NArg() > 0 && flag.Arg(0) != "-" { + var err error + f, err = os.Open(flag.Arg(0)) + if err != nil { + log.Fatal(err) + } + defer f.Close() + } + + positions, err := readPositions(f) + if err != nil { + log.Fatal(err) + } + circuit := make([]int, len(positions)) + for i := range positions { + circuit[i] = i + } + + start := time.Now() + distances := computeDistances(positions) + var last connection + fmt.Println("distances computed in", time.Since(start)) + + start = time.Now() + for i := 0; ; i++ { + if *connections >= 0 && i >= *connections { + break + } + c, ok := distances.FindMin() + if !ok { + break + } + bCircuit := circuit[c.B] + for i := range circuit { + if circuit[i] == bCircuit { + circuit[i] = circuit[c.A] + } + } + if *debug { + fmt.Println("connect", positions[c.A], "and", positions[c.B]) + } + if allEqual(circuit) { + last = c + break + } + delete(distances, c) + } + fmt.Println("connections computed in", time.Since(start)) + + countsMap := make(map[int]int) + for _, c := range circuit { + countsMap[c]++ + } + counts := slices.Sorted(maps.Values(countsMap)) + // if *debug { + // fmt.Println("counts:", counts) + // } + + ans := 1 + for _, c := range counts[max(0, len(counts)-3):] { + ans *= c + } + fmt.Println("three largest mult:", ans) + fmt.Println("last connection X mult:", positions[last.A].X*positions[last.B].X) +} + +type position struct { + X, Y, Z int +} + +func (p position) String() string { + return fmt.Sprintf("%d,%d,%d", p.X, p.Y, p.Z) +} + +func (p position) DistanceTo(p1 position) float64 { + compX := float64((p.X - p1.X) * (p.X - p1.X)) + compY := float64((p.Y - p1.Y) * (p.Y - p1.Y)) + compZ := float64((p.Z - p1.Z) * (p.Z - p1.Z)) + return math.Sqrt(compX + compY + compZ) +} + +func readPositions(r io.Reader) ([]position, error) { + var positions []position + sc := bufio.NewScanner(r) + for sc.Scan() { + fields := strings.Split(sc.Text(), ",") + if len(fields) != 3 { + return nil, fmt.Errorf("position %q: unexpected number of fields", sc.Text()) + } + x, err := strconv.Atoi(fields[0]) + if err != nil { + return nil, fmt.Errorf("position %q: x: %w", sc.Text(), err) + } + y, err := strconv.Atoi(fields[1]) + if err != nil { + return nil, fmt.Errorf("position %q: y: %w", sc.Text(), err) + } + z, err := strconv.Atoi(fields[2]) + if err != nil { + return nil, fmt.Errorf("position %q: z: %w", sc.Text(), err) + } + positions = append(positions, position{ + X: x, + Y: y, + Z: z, + }) + } + return positions, sc.Err() +} + +type connection struct { + A, B int +} + +func (c connection) Reverse() connection { + return connection{c.B, c.A} +} + +type distances map[connection]float64 + +func (d distances) Get(aIndex, bIndex int) float64 { + c := connection{aIndex, bIndex} + if dist, ok := d[c]; ok { + return dist + } + return d[c.Reverse()] +} + +func (d distances) Set(aIndex, bIndex int, dist float64) { + d[connection{aIndex, bIndex}] = dist +} + +func (d distances) FindMin() (c connection, ok bool) { + for pair, dist := range d { + if !ok || dist < d[c] { + c = pair + ok = true + } + } + return c, ok +} + +func computeDistances(positions []position) distances { + table := make(distances) + for i, p := range positions { + for j := i + 1; j < len(positions); j++ { + dist := p.DistanceTo(positions[j]) + table.Set(i, j, dist) + } + } + return table +} + +func allEqual(s []int) bool { + if len(s) < 1 { + return true + } + for _, v := range s[1:] { + if v != s[0] { + return false + } + } + return true +}