@@ -21,17 +21,34 @@ func readInput() -> Grid {
21
21
return Grid ( items: items, lastNode: . init( x: x - 1 , y: y - 1 ) )
22
22
}
23
23
24
- func shortestPath( grid: Grid ) -> Int ? {
24
+ enum Direction {
25
+ case l, r, u, d
26
+ }
27
+
28
+ struct Cell : Hashable {
29
+ let node : Node
30
+ let direction : Direction
31
+ let moves : Int
32
+ }
33
+
34
+ func shortestPath( grid: Grid , moveRange: ClosedRange < Int > ) -> Int ? {
25
35
let startNode = Node ( x: 0 , y: 0 )
26
- func isEnd( node: Node ) -> Bool { node == grid. lastNode }
36
+ // Setting moves to 0 to allows us to equally consider both left and down
37
+ // neighbours.
38
+ let startCell = Cell ( node: startNode, direction: . l, moves: 0 )
39
+ func isEnd( _ cell: Cell ) -> Bool { cell. node == grid. lastNode }
27
40
28
- var dist : [ Node : Int ] = [ startNode: 0 ]
29
- var seen : Set < Node > = Set ( )
41
+ func adj( _ u: Cell ) -> [ Cell ] {
42
+ neighbours ( grid: grid, moveRange: moveRange, cell: u)
43
+ }
44
+
45
+ var dist : [ Cell : Int ] = [ startCell: 0 ]
46
+ var seen : Set < Cell > = Set ( )
30
47
//var invDist: [Int: [Node]] = []
31
48
//var minDist = 0
32
49
33
- func popNearest( ) -> ( Node , Int ) ? {
34
- var u : Node ?
50
+ func popNearest( ) -> ( Cell , Int ) ? {
51
+ var u : Cell ?
35
52
var du : Int = . max
36
53
for (v, dv) in dist {
37
54
if dv < du && !seen. contains ( v) {
@@ -45,9 +62,9 @@ func shortestPath(grid: Grid) -> Int? {
45
62
46
63
while let ( u, du) = popNearest ( ) {
47
64
if !seen. insert ( u) . inserted { continue }
48
- if isEnd ( node : u) { return du }
49
- for v in neighbours ( grid : grid , node : u) {
50
- let d = grid. items [ v] !
65
+ if isEnd ( u) { return du }
66
+ for v in adj ( u) {
67
+ let d = grid. items [ v. node ] !
51
68
let dv = dist [ v] ?? . max
52
69
if du + d < dv {
53
70
dist [ v] = du + d
@@ -58,13 +75,39 @@ func shortestPath(grid: Grid) -> Int? {
58
75
return nil
59
76
}
60
77
61
- func neighbours( grid: Grid , node: Node ) -> [ Node ] {
78
+ func neighbours( grid: Grid , moveRange: ClosedRange < Int > , cell: Cell ) -> [ Cell ] {
79
+ func make( _ xy: ( Int , Int ) , _ direction: Direction , _ moves: Int ) -> Cell {
80
+ Cell ( node: Node ( x: xy. 0 , y: xy. 1 ) , direction: direction, moves: moves)
81
+ }
82
+
83
+ let node = cell. node
84
+ let moves = cell. moves
62
85
let ( x, y) = ( node. x, node. y)
63
- return [ ( x - 1 , y) , ( x + 1 , y) , ( x, y - 1 ) , ( x, y + 1 ) ]
64
- . map { Node ( x: $0. 0 , y: $0. 1 ) }
65
- . filter { grid. items [ $0] != nil }
86
+ let cells : [ Cell ]
87
+ switch cell. direction {
88
+ case . l:
89
+ cells = [ make ( ( x + 1 , y) , . l, moves + 1 ) ,
90
+ make ( ( x, y - 1 ) , . u, 1 ) ,
91
+ make ( ( x, y + 1 ) , . d, 1 ) ]
92
+ case . r:
93
+ cells = [ make ( ( x - 1 , y) , . r, moves + 1 ) ,
94
+ make ( ( x, y - 1 ) , . u, 1 ) ,
95
+ make ( ( x, y + 1 ) , . d, 1 ) ]
96
+ case . u:
97
+ cells = [ make ( ( x, y - 1 ) , . u, moves + 1 ) ,
98
+ make ( ( x - 1 , y) , . r, 1 ) ,
99
+ make ( ( x + 1 , y) , . l, 1 ) ]
100
+ case . d:
101
+ cells = [ make ( ( x, y + 1 ) , . d, moves + 1 ) ,
102
+ make ( ( x - 1 , y) , . r, 1 ) ,
103
+ make ( ( x + 1 , y) , . l, 1 ) ]
104
+ }
105
+ return cells
106
+ . filter { grid. items [ $0. node] != nil }
107
+ . filter { moveRange. contains ( $0. moves) }
66
108
}
67
109
68
110
let grid = readInput ( )
69
- let sp = shortestPath ( grid: grid)
70
- print ( sp ?? 0 )
111
+ let p1 = shortestPath ( grid: grid, moveRange: 1 ... 3 )
112
+ // let p1 = shortestPath(grid: grid, moveRange: 4...10)
113
+ print ( p1 ?? 0 )
0 commit comments