Skip to content

Commit 5ea88db

Browse files
committed
Optimize 2025 day 8 using PriorityQueue
1 parent 00452ed commit 5ea88db

File tree

1 file changed

+19
-9
lines changed
  • src/main/scala/eu/sim642/adventofcode2025

1 file changed

+19
-9
lines changed

src/main/scala/eu/sim642/adventofcode2025/Day8.scala

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import eu.sim642.adventofcodelib.IteratorImplicits.*
44
import eu.sim642.adventofcodelib.graph.Kruskal
55
import eu.sim642.adventofcodelib.pos.Pos3
66

7+
import scala.collection.mutable
8+
79
object Day8 {
810

911
extension (pos: Pos3) {
@@ -13,20 +15,28 @@ object Day8 {
1315
}
1416
}
1517

16-
def closestPairsSeq(junctionBoxes: Seq[Pos3]): Seq[(Pos3, Pos3)] = {
17-
//noinspection ConvertibleToMethodValue
18-
(for {
18+
extension [A](queue: mutable.PriorityQueue[A]) {
19+
// normal queue.iterator does not yield dequeue order
20+
def dequeueIterator: Iterator[A] = new Iterator[A] {
21+
override def hasNext: Boolean = queue.nonEmpty
22+
23+
override def next(): A = queue.dequeue()
24+
}
25+
}
26+
27+
def iterateClosestPairs(junctionBoxes: Seq[Pos3]): Iterator[(Pos3, Pos3)] = {
28+
// it is faster to use a PriorityQueue than sort the Seq of all pairs because Kruskal will only need some closest pairs, not all
29+
val queue = mutable.PriorityQueue.empty[((Pos3, Pos3), Long)](using Ordering.by(-_._2))
30+
for {
1931
// faster than combinations(2)
2032
(p1, i) <- junctionBoxes.iterator.zipWithIndex
2133
p2 <- junctionBoxes.view.slice(i + 1, junctionBoxes.size).iterator
22-
} yield (p1, p2) -> (p1 euclideanDistanceSqr p2)) // no need to sqrt distance just for sorting
23-
.toSeq
24-
.sortBy(_._2)
25-
.map(_._1)
34+
} queue.enqueue((p1, p2) -> (p1 euclideanDistanceSqr p2)) // no need to sqrt distance just for sorting
35+
queue.dequeueIterator.map(_._1)
2636
}
2737

2838
def multiplySizesAfter(junctionBoxes: Seq[Pos3], after: Int = 1000, sizes: Int = 3): Int = {
29-
val closestPairs = closestPairsSeq(junctionBoxes)
39+
val closestPairs = iterateClosestPairs(junctionBoxes)
3040
val (ufAfter, _) = Kruskal.iterate(junctionBoxes, closestPairs)(after)
3141

3242
ufAfter.groups()
@@ -38,7 +48,7 @@ object Day8 {
3848

3949
// TODO: deduplicate
4050
def multiplyLastXs(junctionBoxes: Seq[Pos3]): Int = {
41-
val closestPairs = closestPairsSeq(junctionBoxes)
51+
val closestPairs = iterateClosestPairs(junctionBoxes)
4252
val lastPair = Kruskal.iterateEdges(junctionBoxes, closestPairs).last
4353
lastPair._1.x * lastPair._2.x
4454
}

0 commit comments

Comments
 (0)