Skip to content

Commit f1f1c0f

Browse files
committed
feat(angch/2025-08): Use heap
1 parent 275eed7 commit f1f1c0f

File tree

1 file changed

+50
-46
lines changed

1 file changed

+50
-46
lines changed

angch/2025-08/main.go

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,54 @@ package main
22

33
import (
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
1454
func 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

Comments
 (0)