@@ -36,58 +36,56 @@ val xRange = grid.head.indices
36
36
val yRange = grid.indices
37
37
38
38
case class Point (x : Int , y : Int ):
39
- def inBounds = xRange.contains(x) && yRange.contains(y)
40
-
41
39
def move (dir : Dir ) = dir match
42
40
case Dir .N => copy(y = y - 1 )
43
41
case Dir .S => copy(y = y + 1 )
44
42
case Dir .E => copy(x = x + 1 )
45
43
case Dir .W => copy(x = x - 1 )
46
44
45
+ def inBounds (p : Point ) =
46
+ xRange.contains(p.x) && yRange.contains(p.y)
47
+
47
48
def heatLoss (p : Point ) =
48
- if p. inBounds then grid(p.y)(p.x) else 0
49
+ if inBounds(p) then grid(p.y)(p.x) else 0
49
50
50
- case class State (pos : Point , dir : Dir , streak : Int , totalHeatLoss : Int ):
51
+ case class State (pos : Point , dir : Dir , streak : Int ):
51
52
def straight : State =
52
- val newPos = pos.move(dir)
53
- State (pos.move(dir), dir, streak + 1 , totalHeatLoss + heatLoss(newPos))
53
+ State (pos.move(dir), dir, streak + 1 )
54
54
55
55
def turnLeft : State =
56
56
val newDir = dir.turnLeft
57
- val newPos = pos.move(newDir)
58
- State (newPos, newDir, 1 , totalHeatLoss + heatLoss(newPos))
57
+ State (pos.move(newDir), newDir, 1 )
59
58
60
59
def turnRight : State =
61
60
val newDir = dir.turnRight
62
- val newPos = pos.move(newDir)
63
- State (pos.move(newDir), newDir, 1 , totalHeatLoss + heatLoss(newPos))
61
+ State (pos.move(newDir), newDir, 1 )
64
62
65
63
def nextStates : List [State ] =
66
64
List (straight, turnLeft, turnRight).filter: s =>
67
- s.pos.inBounds && s.streak <= 3
65
+ inBounds( s.pos) && s.streak <= 3
68
66
69
67
def nextStates2 : List [State ] =
70
68
if streak < 4 then List (straight)
71
69
else List (straight, turnLeft, turnRight).filter: s =>
72
- s.pos.inBounds && s.streak <= 10
73
-
74
- def motion = (pos, dir, streak)
70
+ inBounds(s.pos) && s.streak <= 10
75
71
76
72
def search (next : State => List [State ]): Int =
77
- import collection .mutable .{PriorityQueue , Set }
73
+ import collection .mutable .{PriorityQueue , Map }
74
+
75
+ val minHeatLoss = Map .empty[State , Int ]
78
76
79
- given Ordering [State ] = Ordering .by(_.totalHeatLoss )
77
+ given Ordering [State ] = Ordering .by(minHeatLoss )
80
78
val pq = PriorityQueue .empty[State ].reverse
81
79
82
- var visiting = State (Point (0 , 0 ), Dir .E , 0 , 0 )
83
- val visited = Set (visiting.motion)
80
+ var visiting = State (Point (0 , 0 ), Dir .E , 0 )
81
+ minHeatLoss (visiting) = 0
84
82
85
83
val end = Point (xRange.max, yRange.max)
86
84
while visiting.pos != end do
87
- val states = next(visiting).filterNot(s => visited(s.motion) )
88
- states.foreach( s => s " enqueuing: $s " )
89
- pq.enqueue(states * )
90
- visited ++= states.map(_.motion )
85
+ val states = next(visiting).filterNot(minHeatLoss.contains )
86
+ states.foreach: s =>
87
+ minHeatLoss(s) = minHeatLoss(visiting) + heatLoss(s.pos )
88
+ pq.enqueue(s )
91
89
visiting = pq.dequeue()
92
90
93
- visiting.totalHeatLoss
91
+ minHeatLoss( visiting)
0 commit comments