Day 16: Use two stacks instead of PQ

This commit is contained in:
Christian
2025-01-24 17:22:19 +01:00
parent 65b220007e
commit 9654c59bfd

View File

@@ -16,26 +16,34 @@ object Day16 extends Solver(16):
case class State(distance: Int, pose: Pose) case class State(distance: Int, pose: Pose)
implicit def ord: Ordering[State] = Ordering.by(-1 * _.distance) implicit def ord: Ordering[State] = Ordering.by(-1 * _.distance)
Direction.Up.ordinal
def search(start: Pose): (Map[Pose, Int], Map[Pose, List[Pose]]) = def search(start: Pose): (Map[Pose, Int], Map[Pose, List[Pose]]) =
val distance = mutable.Map(start -> 0) val distance = mutable.Map(start -> 0)
val ancestor = mutable.Map.empty[Pose, List[Pose]] val ancestor = mutable.Map.empty[Pose, List[Pose]]
val heap = mutable.PriorityQueue(State(0, start)) var near = mutable.Stack(State(0, start))
var far = mutable.Stack.empty[State]
inline def relax(u: Pose, v: Pose, vDist: Int): Unit = inline def relax(u: Pose, v: Pose, vDist: Int, isFar: Boolean): Unit =
val oldDist = distance.getOrElse(v, 1_000_000) val oldDist = distance.getOrElse(v, 1_000_000)
if vDist == oldDist then ancestor(v) +:= u if vDist == oldDist then ancestor(v) +:= u
if vDist < oldDist then if vDist < oldDist then
ancestor(v) = List(u) ancestor(v) = List(u)
distance(v) = vDist distance(v) = vDist
heap.enqueue(State(vDist, v)) if isFar
then far.push(State(vDist, v))
else near.push(State(vDist, v))
while heap.nonEmpty do while near.nonEmpty do
val State(uDist, u) = heap.dequeue() while near.nonEmpty do
if uDist == distance(u) then val State(uDist, u) = near.pop()
if !grid(u.step.pos).contains('#') then relax(u, u.step, uDist + 1) if uDist == distance(u) then
for (v <- Seq(u.turnLeft, u.turnRight)) do relax(u, v, uDist + 1000) if !grid(u.step.pos).contains('#') then
relax(u, u.step, uDist + 1, false)
for (v <- Seq(u.turnLeft, u.turnRight)) do
relax(u, v, uDist + 1000, true)
val tmp = near
near = far
far = tmp
(distance.toMap, ancestor.toMap) (distance.toMap, ancestor.toMap)