@@ -17,46 +17,55 @@ data class Vec2(val x: Int, val y: Int) {
17
17
operator fun plus (rhs : Vec2 ) = Vec2 (x + rhs.x, y + rhs.y)
18
18
}
19
19
20
- data class Node (val total : Int , val pos : Vec2 , val dir : Vec2 )
20
+ data class Node (val total : Int , val visited : Set <Vec2 >, val pos : Vec2 , val dir : Vec2 )
21
+
22
+ data class ShortestPaths (val length : Int , val visited : Set <Vec2 >)
21
23
22
24
data class Board (val rows : List <String >) {
23
25
val height: Int get() = rows.size
24
26
val width: Int get() = rows[0 ].length
25
27
26
28
operator fun get (pos : Vec2 ): Char = rows[pos.y][pos.x]
27
29
28
- fun shortestPath (start : Vec2 , end : Vec2 ): Int {
30
+ fun shortestPaths (start : Vec2 , end : Vec2 ): ShortestPaths {
29
31
// Your run-of-the-mill Dijkstra implementation below
30
32
31
33
val queue = PriorityQueue <Node >(11 ) { l, r -> l.total - r.total }
32
34
val visited = mutableSetOf<Pair <Vec2 , Vec2 >>()
33
35
34
36
val startDir: Vec2 = Vec2 (1 , 0 )
35
- queue.add(Node (0 , start, startDir))
37
+ queue.add(Node (0 , setOf (start), start, startDir))
36
38
visited.add(Pair (start, startDir))
37
39
40
+ var shortestTotal: Int? = null
41
+ val shortestPaths = mutableSetOf<Vec2 >()
42
+
38
43
while (! queue.isEmpty()) {
39
44
val node = queue.poll()
45
+ if (shortestTotal?.let { node.total > it } ? : false ) {
46
+ break
47
+ }
40
48
if (node.pos == end) {
41
- return node.total
49
+ shortestTotal = node.total
50
+ shortestPaths.addAll(node.visited)
42
51
}
43
52
visited.add(Pair (node.pos, node.dir))
44
53
45
54
// Step
46
55
val next = node.pos + node.dir
47
56
if (Pair (next, node.dir) !in visited && this [next] != ' #' ) {
48
- queue.add(Node (node.total + 1 , next, node.dir))
57
+ queue.add(Node (node.total + 1 , node.visited.union( listOf (next)), next, node.dir))
49
58
}
50
59
51
60
// Rotate
52
61
for (dir in listOf (node.dir.rotateCW(), node.dir.rotateCCW())) {
53
62
if (Pair (node.pos, dir) !in visited) {
54
- queue.add(Node (node.total + 1000 , node.pos, dir))
63
+ queue.add(Node (node.total + 1000 , node.visited, node. pos, dir))
55
64
}
56
65
}
57
66
}
58
67
59
- throw RuntimeException (" No path found" )
68
+ return shortestTotal?. let { ShortestPaths (it, shortestPaths) } ? : throw RuntimeException (" No path found" )
60
69
}
61
70
}
62
71
@@ -66,4 +75,6 @@ val board = Board(File(args[0]).readLines())
66
75
val start = Vec2 (1 , board.height - 2 )
67
76
val end = Vec2 (board.width - 2 , 1 )
68
77
69
- println (" Part 1: ${board.shortestPath(start, end)} " )
78
+ val result = board.shortestPaths(start, end)
79
+ println (" Part 1: ${result.length} " )
80
+ println (" Part 2: ${result.visited.size} " )
0 commit comments