@@ -59,103 +59,81 @@ func PartOne(bytePositions [][2]int) int {
5959 corrupted := make (map [[2 ]int ]struct {})
6060 n := 1 << 10 // 1024
6161 gridSize := 71
62- end := [2 ]int {gridSize - 1 , gridSize - 1 }
6362
6463 for i := range n {
6564 bytePos := bytePositions [i ]
6665 corrupted [bytePos ] = struct {}{}
6766 }
6867
69- seen := make (map [[2 ]int ]struct {})
70- queue := [][3 ]int {{}}
71-
72- var minSteps int
73- for len (queue ) > 0 {
74- curr := queue [0 ]
75- pos := [2 ]int {curr [X ], curr [Y ]}
76- queue = queue [1 :]
77-
78- if _ , ok := seen [pos ]; ok {
79- continue
80- }
81-
82- if _ , ok := corrupted [pos ]; ok {
83- continue
84- }
85-
86- if pos [X ] < 0 || pos [X ] >= gridSize || pos [Y ] < 0 || pos [Y ] >= gridSize {
87- continue
88- }
89-
90- if pos == end {
91- minSteps = curr [Steps ]
92- break
93- }
94-
95- for _ , dir := range directions {
96- queue = append (queue , [3 ]int {curr [X ] + dir [X ], curr [Y ] + dir [Y ], curr [Steps ] + 1 })
97- }
98-
99- seen [pos ] = struct {}{}
100- }
101-
102- return minSteps
68+ return solve (gridSize , corrupted )
10369}
10470
10571func PartTwo (bytePositions [][2 ]int ) string {
10672 corrupted := make (map [[2 ]int ]struct {})
10773 n := 1 << 10 // 1024
10874 gridSize := 71
109- end := [2 ]int {gridSize - 1 , gridSize - 1 }
11075
11176 for i := range n {
11277 bytePos := bytePositions [i ]
11378 corrupted [bytePos ] = struct {}{}
11479 }
11580
81+ // incrementally add the remaining bytes until we find the
82+ // first run without a solution
11683 var blockingByte [2 ]int
11784 for ; n < len (bytePositions ); n ++ {
118- seen := make (map [[2 ]int ]struct {})
119- queue := [][3 ]int {{}}
12085 bytePos := bytePositions [n ]
12186 corrupted [bytePos ] = struct {}{}
12287
123- var minSteps int
124- for len (queue ) > 0 {
125- curr := queue [0 ]
126- pos := [2 ]int {curr [X ], curr [Y ]}
127- queue = queue [1 :]
88+ minSteps := solve (gridSize , corrupted )
12889
129- if _ , ok := seen [pos ]; ok {
130- continue
131- }
90+ // the first square to block the path occurs on the first run where there's
91+ // no solution i.e minSteps == 0
92+ if minSteps == 0 {
93+ blockingByte = bytePos
94+ break
95+ }
96+ }
13297
133- if _ , ok := corrupted [pos ]; ok {
134- continue
135- }
98+ return fmt .Sprintf ("%d,%d" , blockingByte [X ], blockingByte [Y ])
99+ }
136100
137- if pos [ X ] < 0 || pos [ X ] >= gridSize || pos [ Y ] < 0 || pos [ Y ] >= gridSize {
138- continue
139- }
101+ func solve ( gridSize int , corrupted map [[ 2 ] int ] struct {}) int {
102+ seen := make ( map [[ 2 ] int ] struct {})
103+ endPos := [ 2 ] int { gridSize - 1 , gridSize - 1 }
140104
141- if pos == end {
142- minSteps = curr [Steps ]
143- break
144- }
105+ startNode := [3 ]int {}
106+ queue := [][3 ]int {startNode }
145107
146- for _ , dir := range directions {
147- queue = append (queue , [3 ]int {curr [X ] + dir [X ], curr [Y ] + dir [Y ], curr [Steps ] + 1 })
148- }
108+ var minSteps int
109+ for len (queue ) > 0 {
110+ currNode := queue [0 ]
111+ curPos := [2 ]int {currNode [X ], currNode [Y ]}
112+ queue = queue [1 :]
149113
150- seen [pos ] = struct {}{}
114+ if _ , ok := seen [curPos ]; ok {
115+ continue
151116 }
152117
153- // we never reached the end square
154- if minSteps == 0 {
155- blockingByte = bytePos
118+ if _ , ok := corrupted [curPos ]; ok {
119+ continue
120+ }
121+
122+ if curPos [X ] < 0 || curPos [X ] >= gridSize || curPos [Y ] < 0 || curPos [Y ] >= gridSize {
123+ continue
124+ }
125+
126+ if curPos == endPos {
127+ minSteps = currNode [Steps ]
156128 break
157129 }
130+
131+ for _ , dir := range directions {
132+ queue = append (queue , [3 ]int {currNode [X ] + dir [X ], currNode [Y ] + dir [Y ], currNode [Steps ] + 1 })
133+ }
134+
135+ seen [curPos ] = struct {}{}
158136 }
159137
160- return fmt . Sprintf ( "%d,%d" , blockingByte [ X ], blockingByte [ Y ])
138+ return minSteps
161139}
0 commit comments