@@ -9,10 +9,9 @@ import (
9
9
)
10
10
11
11
const (
12
- bounds = '#'
13
- empty = '.'
14
- visited = '@'
15
- finish = 'E'
12
+ bounds = '#'
13
+ empty = '.'
14
+ finish = 'E'
16
15
)
17
16
18
17
var directions = map [byte ]position {
@@ -24,16 +23,21 @@ var directions = map[byte]position{
24
23
25
24
var grid [][]byte
26
25
var player path
26
+ var visited [][]int
27
27
28
28
func main () {
29
29
file := util .FileFromArgs ()
30
30
scan := bufio .NewScanner (file )
31
31
for scan .Scan () {
32
+ visited = append (visited , make ([]int , len (scan .Bytes ())))
32
33
x := bytes .IndexRune (scan .Bytes (), 'S' )
33
34
if x > - 1 {
34
35
player .X = x
35
36
player .Y = len (grid )
36
37
player .Direction = 'E'
38
+ player .History = []position {
39
+ {player .X , player .Y },
40
+ }
37
41
}
38
42
39
43
gridRow := make ([]byte , len (scan .Bytes ()))
@@ -46,56 +50,98 @@ func main() {
46
50
}
47
51
heap .Init (paths )
48
52
53
+ var finishes []path
49
54
var p path
50
55
for {
56
+ // All shortest paths are found, stop searching!
51
57
if paths .Len () == 0 {
52
- util .PrintMatrix (grid )
53
- fmt .Println (finish )
54
- panic ("No path found..." )
58
+ break
55
59
}
56
60
57
61
p = heap .Pop (paths ).(path )
58
62
if grid [p.Y ][p.X ] == finish {
59
- fmt .Println (p .Score )
60
- break
63
+ if len (finishes ) == 0 || p .Score == finishes [0 ].Score {
64
+ fmt .Println (p .Score ) // Part 1
65
+ finishes = append (finishes , p ) // Part 2: Find all shortest routes
66
+ }
67
+ continue
68
+ }
69
+
70
+ // Don't bother paths that are higher than the finish
71
+ if p .Score > 109516 { // 109516 is the input answer for part 1 ;)
72
+ continue
61
73
}
62
74
63
75
var dx , dy int
76
+ outer:
64
77
for d , dd := range directions {
65
78
dx , dy = p .X + dd .X , p .Y + dd .Y
66
- if grid [dy ][dx ] == bounds || grid [ dy ][ dx ] == visited {
79
+ if grid [dy ][dx ] == bounds {
67
80
continue
68
81
}
69
- if grid [dy ][dx ] == empty {
70
- grid [dy ][dx ] = visited
82
+
83
+ // Have we been here before?
84
+ for _ , h := range p .History {
85
+ if h .X == dx && h .Y == dy {
86
+ continue outer
87
+ }
71
88
}
72
89
73
- // Going straight on is free
74
- if p .Direction == d {
90
+ // Have we got enough points to be here?
91
+ if visited [dy ][dx ] > 0 && p .Score > visited [dy ][dx ] {
92
+ continue
93
+ }
94
+ visited [dy ][dx ] = p .Score
95
+
96
+ if p .Direction == d { // Going straight on is free
75
97
heap .Push (paths , path {
76
98
X : dx ,
77
99
Y : dy ,
78
100
Score : p .Score + 1 ,
79
101
Direction : d ,
102
+ History : makeHistory (p .History , position {dx , dy }),
103
+ })
104
+ } else { // Turning costs 1000
105
+ heap .Push (paths , path {
106
+ X : dx ,
107
+ Y : dy ,
108
+ Score : p .Score + 1001 ,
109
+ Direction : d ,
110
+ History : makeHistory (p .History , position {dx , dy }),
80
111
})
81
-
82
- continue
83
112
}
113
+ }
114
+ }
84
115
85
- // No going backsies
86
- if directions [ p . Direction ]. X + dd . X == 0 && directions [ p . Direction ]. Y + dd . Y == 0 {
87
- continue
88
- }
116
+ fmt . Println ( finishes )
117
+
118
+ // Part 2: now find unique points
119
+ var count int
89
120
90
- // Turn here
91
- heap .Push (paths , path {
92
- X : dx ,
93
- Y : dy ,
94
- Score : p .Score + 1001 ,
95
- Direction : d ,
96
- })
121
+ for _ , f := range finishes {
122
+ for _ , fh := range f .History {
123
+ if grid [fh.Y ][fh.X ] != 'O' {
124
+ count ++
125
+ grid [fh.Y ][fh.X ] = 'O'
126
+ }
97
127
}
98
128
}
129
+
130
+ util .PrintMatrix (grid )
131
+ fmt .Println (count )
132
+ }
133
+
134
+ // makeHistory creates a brand new slice containing elements from h and p
135
+ func makeHistory (h []position , p position ) []position {
136
+ newSlice := make ([]position , len (h )+ 1 )
137
+
138
+ var i int
139
+ for i = range h {
140
+ newSlice [i ] = position {h [i ].X , h [i ].Y }
141
+ }
142
+ newSlice [i + 1 ] = p
143
+
144
+ return newSlice
99
145
}
100
146
101
147
type position struct {
@@ -106,6 +152,7 @@ type path struct {
106
152
X , Y int
107
153
Score int
108
154
Direction byte
155
+ History []position
109
156
}
110
157
111
158
type pathHeap []path
0 commit comments