@@ -7,68 +7,77 @@ import (
7
7
)
8
8
9
9
func main () {
10
- common .Setup (18 , part1 , nil )
10
+ common .Setup (18 , part1 , part2 )
11
11
}
12
12
13
13
func part1 (
14
14
input string ,
15
15
) string {
16
- out , err := run (input , 70 , 70 , 1024 )
16
+ m := buildMatrix ()
17
+ cs , err := parse (input )
17
18
if err != nil {
18
- return err . Error ( )
19
+ return fmt . Sprintf ( "Failed to parse input: %v" , err )
19
20
}
20
- return fmt .Sprintf ("Shortest path is %d steps" , out )
21
+
22
+ for _ , c := range cs [:1024 ] {
23
+ m [c.Y ][c.X ] = true
24
+ }
25
+
26
+ start := util.Coordinate {X : 0 , Y : 0 }
27
+ end := util.Coordinate {X : 70 , Y : 70 }
28
+ visitedSet := buildVisitedSet [int ]()
29
+ shortestPath (m , start , end , 0 , visitedSet )
30
+
31
+ shortest := visitedSet [70 ][70 ]
32
+ return fmt .Sprintf ("Shortest path is %d steps" , shortest )
21
33
}
22
34
23
- func run (
35
+ func part2 (
24
36
input string ,
25
- maxX int ,
26
- maxY int ,
27
- fallenBytes int ,
28
- ) (int , error ) {
29
- m := buildMatrix (maxX , maxY )
37
+ ) string {
38
+ m := buildMatrix ()
30
39
cs , err := parse (input )
31
40
if err != nil {
32
- return - 1 , err
41
+ return fmt . Sprintf ( "Failed to parse input: %v" , err )
33
42
}
34
43
35
- if len (cs ) > fallenBytes {
36
- cs = cs [:fallenBytes ]
37
- }
44
+ // Initialize everything
45
+ latest := cs [0 ]
46
+ cs = cs [1 :]
47
+ winningSet := buildVisitedSet [bool ]()
48
+ m [latest.Y ][latest.X ] = true
49
+ count := 1
50
+ start := util.Coordinate {X : 0 , Y : 0 }
51
+ end := util.Coordinate {X : 70 , Y : 70 }
52
+ success := anyPath (m , start , end , buildVisitedSet [bool ](), winningSet )
38
53
39
- for _ , c := range cs {
40
- m [c.Y ][c.X ] = true
41
- }
54
+ for success && len (cs ) > 0 {
55
+ for ! winningSet [latest.Y ][latest.X ] && len (cs ) > 0 {
56
+ count ++
57
+ latest = cs [0 ]
58
+ cs = cs [1 :]
59
+ m [latest.Y ][latest.X ] = true
60
+ }
42
61
43
- visitedSet := buildVisitedSet (maxY )
44
- shortestPath (
45
- m ,
46
- util.Coordinate {X : 0 , Y : 0 },
47
- util.Coordinate {X : maxX , Y : maxY },
48
- 0 ,
49
- visitedSet ,
50
- )
62
+ winningSet = buildVisitedSet [bool ]()
63
+ success = anyPath (m , start , end , buildVisitedSet [bool ](), winningSet )
64
+ }
51
65
52
- return visitedSet [ maxY ][ maxX ], nil
66
+ return fmt . Sprintf ( "The byte that broke the camel's back was %s" , latest )
53
67
}
54
68
55
- func buildMatrix (
56
- maxX int ,
57
- maxY int ,
58
- ) [][]bool {
59
- out := make ([][]bool , maxY + 1 )
60
- for y := 0 ; y <= maxY ; y ++ {
61
- out [y ] = make ([]bool , maxX + 1 )
69
+ func buildMatrix () [][]bool {
70
+ out := make ([][]bool , 71 )
71
+ for y := 0 ; y <= 70 ; y ++ {
72
+ out [y ] = make ([]bool , 71 )
62
73
}
63
74
return out
64
75
}
65
76
66
- func buildVisitedSet (
67
- maxY int ,
68
- ) map [int ]map [int ]int {
69
- visitedSet := make (map [int ]map [int ]int )
70
- for y := 0 ; y <= maxY ; y ++ {
71
- visitedSet [y ] = make (map [int ]int )
77
+ func buildVisitedSet [T any ]() map [int ]map [int ]T {
78
+ visitedSet := make (map [int ]map [int ]T )
79
+ for y := 0 ; y <= 70 ; y ++ {
80
+ visitedSet [y ] = make (map [int ]T )
72
81
}
73
82
return visitedSet
74
83
}
@@ -106,3 +115,31 @@ func shortestPath(
106
115
shortestPath (m , c .South (), goal , steps + 1 , visitedSet )
107
116
shortestPath (m , c .West (), goal , steps + 1 , visitedSet )
108
117
}
118
+
119
+ func anyPath (
120
+ m [][]bool ,
121
+ c util.Coordinate ,
122
+ goal util.Coordinate ,
123
+ visitedSet map [int ]map [int ]bool ,
124
+ winningSet map [int ]map [int ]bool ,
125
+ ) bool {
126
+ if visitedSet [c.Y ][c.X ] || ! util .In2DArray (c , m ) || m [c.Y ][c.X ] {
127
+ // Been here, outside matrix or position is impassable
128
+ return false
129
+ } else if c .Equals (goal ) {
130
+ // We did it!
131
+ winningSet [c.Y ][c.X ] = true
132
+ return true
133
+ }
134
+
135
+ visitedSet [c.Y ][c.X ] = true
136
+ winner := anyPath (m , c .South (), goal , visitedSet , winningSet ) ||
137
+ anyPath (m , c .East (), goal , visitedSet , winningSet ) ||
138
+ anyPath (m , c .West (), goal , visitedSet , winningSet ) ||
139
+ anyPath (m , c .North (), goal , visitedSet , winningSet )
140
+ if winner {
141
+ winningSet [c.Y ][c.X ] = true
142
+ }
143
+
144
+ return winner
145
+ }
0 commit comments