@@ -3,18 +3,20 @@ package main
3
3
import (
4
4
"advent-of-code/util"
5
5
"bufio"
6
- "bytes"
7
6
"fmt"
8
7
)
9
8
10
9
const (
11
- boundry = '#'
12
- box = 'O'
13
- empty = '.'
14
- up = '^'
15
- right = '>'
16
- down = 'v'
17
- left = '<'
10
+ boundry = '#'
11
+ box = 'O'
12
+ boxLeft = '['
13
+ boxRight = ']'
14
+ empty = '.'
15
+
16
+ up = '^'
17
+ right = '>'
18
+ down = 'v'
19
+ left = '<'
18
20
)
19
21
20
22
var moves = map [byte ]position {
@@ -24,51 +26,77 @@ var moves = map[byte]position{
24
26
left : {- 1 , 0 },
25
27
}
26
28
27
- var grid [][]byte
28
- var robot position
29
+ var grid , grid2 [][]byte
30
+ var robot , robot2 position
29
31
30
32
func main () {
31
33
file := util .FileFromArgs ()
32
34
scan := bufio .NewScanner (file )
33
35
34
36
// Read grid
35
- var x int
36
37
for scan .Scan () {
37
38
row := scan .Bytes ()
38
39
if len (row ) == 0 {
39
40
break
40
41
}
41
42
42
- x = bytes .IndexRune (row , '@' )
43
- if x > - 1 {
44
- robot .X = x
45
- robot .Y = len (grid )
46
- }
47
-
48
- // Prevent scanner memory override
43
+ // Part 1: Prevent scanner memory override
49
44
gridRow := make ([]byte , len (row ))
50
45
copy (gridRow , row )
51
46
grid = append (grid , gridRow )
47
+
48
+ // Part 2
49
+ gridRow = make ([]byte , 0 , len (row )* 2 )
50
+ for x , b := range row {
51
+ switch b {
52
+ case '@' :
53
+ robot .X = x
54
+ robot .Y = len (grid ) - 1
55
+ robot2 .X = 2 * x
56
+ robot2 .Y = len (grid2 )
57
+ gridRow = append (gridRow , '@' , empty )
58
+ case boundry :
59
+ gridRow = append (gridRow , boundry , boundry )
60
+ case box :
61
+ gridRow = append (gridRow , boxLeft , boxRight )
62
+ case empty :
63
+ gridRow = append (gridRow , empty , empty )
64
+ }
65
+ }
66
+ grid2 = append (grid2 , gridRow )
52
67
}
53
68
69
+ util .PrintMatrix (grid2 )
70
+
54
71
// Move stuf arround
55
72
for scan .Scan () {
56
73
for _ , b := range scan .Bytes () {
57
74
moveObject (robot .X , robot .Y , b , true )
75
+ moveObject2 (robot2 .X , robot2 .Y , b , true )
76
+
77
+ // util.PrintMatrix(grid2)
58
78
}
59
79
}
60
80
61
81
// Find boxes in our grid
62
- var result int
82
+ var result , result2 int
63
83
for y := range grid {
64
84
for x := range grid [y ] {
65
85
if grid [y ][x ] == box {
66
86
result += 100 * y + x
67
87
}
68
88
}
69
89
}
90
+ for y := range grid2 {
91
+ for x := range grid2 [y ] {
92
+ if grid2 [y ][x ] == boxLeft {
93
+ result2 += 100 * y + x
94
+ }
95
+ }
96
+ }
70
97
71
98
fmt .Println (result )
99
+ fmt .Println (result2 )
72
100
}
73
101
74
102
type position struct {
@@ -98,3 +126,99 @@ func moveObject(x, y int, direction byte, isRobot bool) bool {
98
126
99
127
return true
100
128
}
129
+
130
+ func moveObject2 (x , y int , direction byte , isRobot bool ) bool {
131
+ dx := x + moves [direction ].X
132
+ dy := y + moves [direction ].Y
133
+
134
+ if grid2 [dy ][dx ] == boundry {
135
+ return false
136
+ }
137
+
138
+ // Always start from the left box part
139
+ bx := dx
140
+ if grid2 [dy ][dx ] == boxRight {
141
+ bx -= 1
142
+ }
143
+
144
+ if grid2 [dy ][bx ] == boxLeft {
145
+ switch direction {
146
+ case up :
147
+ if (grid2 [dy - 1 ][bx ] == empty && grid2 [dy - 1 ][bx + 1 ] == empty ) || (grid2 [dy - 1 ][bx ] == boxRight && grid2 [dy - 1 ][bx + 1 ] == boxLeft && can2BoxesMove (bx - 1 , y - 1 , direction ) && moveObject2 (bx , dy , direction , false ) && moveObject2 (bx + 1 , dy , direction , false )) || (grid2 [dy - 1 ][bx ] == boxRight && grid2 [dy - 1 ][bx + 1 ] == empty && moveObject2 (bx , dy , direction , false )) || (grid2 [dy - 1 ][bx + 1 ] == left && grid2 [dy - 1 ][bx ] == empty && moveObject2 (bx , dy , direction , false )) {
148
+ grid2 [dy ][bx ] = empty
149
+ grid2 [dy ][bx + 1 ] = empty
150
+ grid2 [dy - 1 ][bx ] = boxLeft
151
+ grid2 [dy - 1 ][bx + 1 ] = boxRight
152
+ } else {
153
+ return false
154
+ }
155
+ case right :
156
+ if grid2 [dy ][bx + 2 ] == empty || (grid2 [dy ][bx + 2 ] == boxLeft && moveObject2 (bx + 1 , dy , direction , false )) {
157
+ grid2 [dy ][bx ] = empty
158
+ grid2 [dy ][bx + 1 ] = boxLeft
159
+ grid2 [dy ][bx + 2 ] = boxRight
160
+ } else {
161
+ return false
162
+ }
163
+ case down :
164
+ if (grid2 [dy + 1 ][bx ] == empty && grid2 [dy + 1 ][bx + 1 ] == empty ) || (grid2 [dy + 1 ][bx ] == boxLeft && moveObject2 (bx , dy , direction , false )) || (grid2 [dy + 1 ][bx ] == boxRight && grid2 [dy + 1 ][bx + 1 ] == boxLeft && can2BoxesMove (bx - 2 , dy + 1 , direction ) && moveObject2 (bx , dy , direction , false ) && moveObject2 (bx + 1 , dy , direction , false )) || (grid2 [dy + 1 ][bx ] == boxRight && moveObject2 (bx , dy , direction , false ) && grid2 [dy + 1 ][bx + 1 ] == empty ) {
165
+ grid2 [dy ][bx ] = empty
166
+ grid2 [dy ][bx + 1 ] = empty
167
+ grid2 [dy + 1 ][bx ] = boxLeft
168
+ grid2 [dy + 1 ][bx + 1 ] = boxRight
169
+ } else {
170
+ return false
171
+ }
172
+ case left :
173
+ if grid2 [dy ][bx - 1 ] == empty || (grid2 [dy ][bx - 1 ] == boxRight && moveObject2 (bx - 1 , dy , direction , false )) {
174
+ grid2 [dy ][bx + 1 ] = empty
175
+ grid2 [dy ][bx ] = boxRight
176
+ grid2 [dy ][bx - 1 ] = boxLeft
177
+ } else {
178
+ return false
179
+ }
180
+ }
181
+ }
182
+
183
+ // All is well, move the object
184
+ if isRobot {
185
+ grid2 [dy ][dx ] = grid2 [y ][x ]
186
+ grid2 [y ][x ] = empty
187
+
188
+ robot2 .X = dx
189
+ robot2 .Y = dy
190
+ }
191
+
192
+ return true
193
+ }
194
+
195
+ func can2BoxesMove (x , y int , direction byte ) bool {
196
+ if direction == down {
197
+ y += 2
198
+ } else {
199
+ y -= 2
200
+ }
201
+
202
+ if y < 0 || y > len (grid )- 1 || x > len (grid2 [y ])- 4 {
203
+ return true
204
+ }
205
+
206
+ // Obstacles in the way?
207
+ for i := 0 ; i < 4 ; i ++ {
208
+ if grid2 [y ][x + i ] == boundry {
209
+ return false
210
+ }
211
+
212
+ }
213
+
214
+ // One+ box blocking?
215
+ if x > len (grid2 [y ])- 5 {
216
+ for i := - 1 ; i < 5 ; i ++ {
217
+ if grid [y ][x + i ] == boxLeft && grid [y ][x + i + 1 ] == boxRight && ! moveObject2 (x + i , y , direction , false ) {
218
+ return false
219
+ }
220
+ }
221
+ }
222
+
223
+ return true
224
+ }
0 commit comments