Compare commits
2 Commits
65b220007e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d9dc696a8 | ||
|
|
9654c59bfd |
@@ -3,6 +3,8 @@ package dev.ctsk.aoc.days
|
||||
import dev.ctsk.aoc.{Direction, *}
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.util.boundary
|
||||
import scala.util.boundary.break
|
||||
|
||||
object Day16 extends Solver(16):
|
||||
override def run(input_ : os.ReadablePath): (Timings, Solution) =
|
||||
@@ -14,28 +16,40 @@ object Day16 extends Solver(16):
|
||||
val end = grid.findFirst(_ == 'E').get
|
||||
|
||||
case class State(distance: Int, pose: Pose)
|
||||
implicit def ord: Ordering[State] = Ordering.by(-1 * _.distance)
|
||||
|
||||
Direction.Up.ordinal
|
||||
|
||||
def search(start: Pose): (Map[Pose, Int], Map[Pose, List[Pose]]) =
|
||||
val distance = mutable.Map(start -> 0)
|
||||
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)
|
||||
if vDist == oldDist then ancestor(v) +:= u
|
||||
if vDist < oldDist then
|
||||
ancestor(v) = List(u)
|
||||
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
|
||||
val State(uDist, u) = heap.dequeue()
|
||||
if uDist == distance(u) then
|
||||
if !grid(u.step.pos).contains('#') then relax(u, u.step, uDist + 1)
|
||||
for (v <- Seq(u.turnLeft, u.turnRight)) do relax(u, v, uDist + 1000)
|
||||
boundary:
|
||||
while near.nonEmpty do
|
||||
var atEnd = false;
|
||||
while near.nonEmpty do
|
||||
val State(uDist, u) = near.pop()
|
||||
atEnd |= u.pos == end
|
||||
if uDist == distance(u) then
|
||||
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)
|
||||
|
||||
if atEnd then break()
|
||||
|
||||
val tmp = near
|
||||
near = far
|
||||
far = tmp
|
||||
|
||||
(distance.toMap, ancestor.toMap)
|
||||
|
||||
@@ -43,7 +57,7 @@ object Day16 extends Solver(16):
|
||||
search(Pose(start, Direction.Right))
|
||||
}
|
||||
|
||||
val endPose = DIRS.map(Pose(end, _)).minBy(distance(_))
|
||||
val endPose = DIRS.map(Pose(end, _)).minBy(distance.getOrElse(_, 1_000_000))
|
||||
|
||||
val p1 = distance(endPose)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user