@@ -2,14 +2,54 @@ package main
22
33import (
44 "bufio"
5+ "container/heap"
56 "fmt"
67 "log"
78 "os"
8- "slices"
99 "sort"
1010 "time"
1111)
1212
13+ type pairDist struct {
14+ p1 int
15+ p2 int
16+ d int
17+ index int
18+ }
19+
20+ // A PriorityQueue implements heap.Interface and holds Items.
21+ type PriorityQueue []* pairDist
22+
23+ func (pq PriorityQueue ) Len () int { return len (pq ) }
24+
25+ func (pq PriorityQueue ) Less (i , j int ) bool {
26+ // We want Pop to give us the highest, not lowest, priority so we use greater than here.
27+ return pq [i ].d < pq [j ].d
28+ }
29+
30+ func (pq PriorityQueue ) Swap (i , j int ) {
31+ pq [i ], pq [j ] = pq [j ], pq [i ]
32+ pq [i ].index = i
33+ pq [j ].index = j
34+ }
35+
36+ func (pq * PriorityQueue ) Push (x any ) {
37+ n := len (* pq )
38+ item := x .(* pairDist )
39+ item .index = n
40+ * pq = append (* pq , item )
41+ }
42+
43+ func (pq * PriorityQueue ) Pop () any {
44+ old := * pq
45+ n := len (old )
46+ item := old [n - 1 ]
47+ old [n - 1 ] = nil // don't stop the GC from reclaiming the item eventually
48+ item .index = - 1 // for safety
49+ * pq = old [0 : n - 1 ]
50+ return item
51+ }
52+
1353// dist doesn't need actual dist, just enough for sorting
1454func dist (a , b [3 ]int ) int {
1555 x1 , y1 , z1 := a [0 ]- b [0 ], a [1 ]- b [1 ], a [2 ]- b [2 ]
@@ -28,67 +68,36 @@ func day8(file string) (part1, part2 int) {
2868 points := [][3 ]int {}
2969 circuits := [][]int {}
3070 pointInCircuit := map [int ]int {}
31- _ = circuits
3271
3372 for scanner .Scan () {
3473 t := scanner .Text ()
3574 x , y , z := 0 , 0 , 0
3675 fmt .Sscanf (t , "%d,%d,%d" , & x , & y , & z )
3776 points = append (points , [3 ]int {x , y , z })
3877 }
39- // log.Printf("%+v\n", points)
40-
41- type pairDist struct {
42- p1 int
43- p2 int
44- d int
45- }
46- shortest := []pairDist {}
78+ shortest := make (PriorityQueue , 0 , len (points )* (len (points )))
79+ heap .Init (& shortest )
4780
4881 maxConn := len (points )
4982 if maxConn == 20 {
5083 maxConn = 10 // the test is shorter than full run
5184 }
52- shortEntries := maxConn * 5
5385
5486 t1 := time .Now ()
5587 for k1 , v1 := range points {
5688 for k2 := k1 + 1 ; k2 < len (points ); k2 ++ {
5789 v2 := points [k2 ]
58-
59- dist1 := dist (v1 , v2 )
60- if len (shortest ) == shortEntries {
61- if dist1 > shortest [len (shortest )- 1 ].d {
62- continue
63- }
64- }
65-
66- pd := pairDist {k1 , k2 , dist1 }
67- shortest = append (shortest , pd )
68- slices .SortFunc (shortest , func (a , b pairDist ) int {
69- if a .d > b .d {
70- return 1
71- }
72- if a .d < b .d {
73- return - 1
74- }
75- return 0
76- })
77-
78- if len (shortest ) > shortEntries {
79- shortest = shortest [:shortEntries ]
80- }
90+ pd := pairDist {k1 , k2 , dist (v1 , v2 ), 0 }
91+ heap .Push (& shortest , & pd )
8192 }
8293 }
8394 t2 := time .Now ()
8495
85- // fmt.Printf("%+v\n", shortest)
86- // log.Fatal("a")
8796 count := 0
88- for k , pd := range shortest {
89- // log.Printf("%d %d %d %f %+v\n", k, pd.p1, pd.p2, pd.d, pointInCircuit)
90-
91- // log.Printf("%d/%d: b4 %+v %+v %+v\n", k, count, circuits, pointInCircuit, len(points)-len(pointInCircuit) )
97+ k := - 1
98+ for {
99+ k ++
100+ pd := heap . Pop ( & shortest ).( * pairDist )
92101 if k == maxConn {
93102 lens := []int {}
94103 for _ , v := range circuits {
@@ -103,10 +112,8 @@ func day8(file string) (part1, part2 int) {
103112
104113 if pointInCircuit [pd .p1 ] > 0 && pointInCircuit [pd .p2 ] > 0 &&
105114 pointInCircuit [pd .p1 ] == pointInCircuit [pd .p2 ] {
106- // fmt.Println("Same circuit", points[pd.p1], points[pd.p2])
115+ // Already in, do nothing
107116 } else if pointInCircuit [pd .p1 ] > 0 && pointInCircuit [pd .p2 ] > 0 {
108- // log.Fatal("Combine!")
109-
110117 nc := pointInCircuit [pd .p1 ] - 1
111118 nc2 := pointInCircuit [pd .p2 ] - 1
112119 circuits [nc ] = append (circuits [nc ], circuits [nc2 ]... )
@@ -115,7 +122,6 @@ func day8(file string) (part1, part2 int) {
115122 pointInCircuit [v2 ] = nc + 1
116123 }
117124 circuits [nc2 ] = []int {}
118-
119125 count ++
120126 } else if pointInCircuit [pd .p1 ] > 0 {
121127 nc := pointInCircuit [pd .p1 ] - 1
@@ -151,12 +157,10 @@ func day8(file string) (part1, part2 int) {
151157 part2 = points [pd .p1 ][0 ] * points [pd .p2 ][0 ]
152158 break
153159 }
154-
155160 }
156161
157162 t3 := time .Now ()
158163 fmt .Println ("Time" , t2 .Sub (t1 ), t3 .Sub (t2 ))
159- // log.Printf("circuits %+v %v\n", circuits, len(circuits[0]))
160164 return
161165}
162166
0 commit comments