@@ -110,10 +110,44 @@ def makePads(robots: Int): List[Pad] = List.fill(robots)(Pad(PadType.Dir)) :+ Pa
110
110
111
111
def makeState (robots : Int ) = State (makePads(robots))
112
112
113
- def solve (robots : Int , goals : List [String ]): Int =
114
- val state = makeState(robots)
113
+ def cost (robots : Int , pos : Vec2 , action : Char ): Int = 1
114
+
115
+ def shortestProgramLength (robots : Int , goal : String ): Int =
116
+ case class Node (pos : Vec2 , output : String = " " , total : Int = 0 ) extends Ordered [Node ] {
117
+ def compare (that : Node ): Int = that.total compare total // Intentionally reversed for min-heap
118
+ }
119
+
120
+ // Your run-of-the-mill Dijkstra implementation (this time on the numpad)
121
+
122
+ val queue = mutable.PriorityQueue [Node ]()
123
+ val visited = mutable.HashSet [(Vec2 , String )]()
124
+
125
+ val startPos = PadType .Num .locate('A' )
126
+ val start = Node (startPos)
127
+ queue.enqueue(start)
128
+ visited.add((start.pos, start.output))
129
+
130
+ while ! queue.isEmpty do
131
+ val node = queue.dequeue()
132
+ if node.output == goal then
133
+ return node.total
134
+
135
+ if node.output.length < goal.length then
136
+ for
137
+ action <- ACTIONS
138
+ do
139
+ val newPos = node.pos + DIRECTIONS .get(action).getOrElse(Vec2 (0 , 0 ))
140
+ if PAD_LAYOUTS (PadType .Num ).contains(newPos) then
141
+ val newOutput = if action == 'A' then node.output.appended(PAD_LAYOUTS (PadType .Num )(node.pos)) else node.output
142
+ if ! visited.contains((newPos, newOutput)) then
143
+ visited.add((newPos, newOutput))
144
+ queue.enqueue(Node (newPos, newOutput, node.total + cost(robots, node.pos, action)))
145
+
146
+ throw new RuntimeException (" No shortest program found" )
147
+
148
+ def solve (robots : Int , goals : List [String ], func : (Int , String ) => Int ): Int =
115
149
goals.map { goal =>
116
- val shortest = shortestProgram(state , goal).length
150
+ val shortest = func(robots , goal)
117
151
shortest * goal.dropRight(1 ).toInt
118
152
}.sum
119
153
@@ -122,5 +156,8 @@ def solve(robots: Int, goals: List[String]): Int =
122
156
// println(s"Part 1: ${solve(2, goals)}")
123
157
// println(s"Part 2: ${solve(25, goals)}")
124
158
125
- for c <- ('0' to '5' ) do
126
- println(s " $c -> ${(0 to 3 ).map { i => shortestProgram(makeState(i), s " $c" ).length }}" )
159
+ for i <- (0 to 3 ) do
160
+ println(s " ${solve(i, goals, { (r, g) => shortestProgram(makeState(r), g).length })} vs ${solve(i, goals, shortestProgramLength)}" )
161
+
162
+ // for c <- ('0' to '5') do
163
+ // println(s"$c -> ${(0 to 3).map { i => shortestProgram(makeState(i), s"$c").length }}")
0 commit comments