@@ -25,14 +25,14 @@ var directions = []util.Direction{
25
25
}
26
26
27
27
type parsedInput struct {
28
- Guard Coordinate
29
- Direction direction
30
- ObstacleMap BoolMatrix
31
- VisitedMap tVisitedMap
28
+ Guard Coordinate
29
+ Direction direction
30
+ ObstacleMatrix BoolMatrix
31
+ VisitedMap tVisitedMap
32
32
}
33
33
34
34
func main () {
35
- common .Setup (6 , part1 , nil )
35
+ common .Setup (6 , part1 , part2 )
36
36
}
37
37
38
38
func part1 (
@@ -55,6 +55,55 @@ func part1(
55
55
return fmt .Sprintf ("Visited spots in the Matrix: %d" , count )
56
56
}
57
57
58
+ func part2 (
59
+ input string ,
60
+ ) string {
61
+ // Solve part 1 first to know where to place obstacles
62
+ original , err := parseInput (input )
63
+ if err != nil {
64
+ return fmt .Sprintf ("Failed to parse input: %v" , err )
65
+ }
66
+
67
+ originalX := original .Guard .X
68
+ originalY := original .Guard .Y
69
+ for original .move () {
70
+ // Do nothing, move() does all the work
71
+ }
72
+
73
+ // Then loop through all positions the guard will visit and place an obstacle
74
+ count := 0
75
+ attempts := 0
76
+ //for x := 0; x <= original.ObstacleMatrix.MaxX; x++ {
77
+ for x , yMap := range original .VisitedMap {
78
+ //for y := 0; y <= original.ObstacleMatrix.MaxY; y++ {
79
+ for y := range yMap {
80
+ if y == originalY && x == originalX {
81
+ continue
82
+ }
83
+ attempts ++
84
+
85
+ // Reset the map with the new obstacle
86
+ original .Guard = Coordinate {X : originalX , Y : originalY }
87
+ original .Direction = 0
88
+ original .VisitedMap = make (tVisitedMap )
89
+ _ = original .ObstacleMatrix .Set (x , y , true )
90
+
91
+ // Run this variant
92
+ for original .move () {
93
+ // Do nothing, move() does all the work
94
+ }
95
+ _ = original .ObstacleMatrix .Set (x , y , false )
96
+
97
+ // If the guard is still in the matrix, he's in a loop
98
+ if original .guardIsInMatrix () {
99
+ count += 1
100
+ }
101
+ }
102
+ }
103
+
104
+ return fmt .Sprintf ("%d of the available %d positions make him loopy!" , count , attempts )
105
+ }
106
+
58
107
func parseInput (
59
108
input string ,
60
109
) (parsedInput , error ) {
@@ -92,47 +141,51 @@ func parseInput(
92
141
}
93
142
94
143
out := parsedInput {
95
- Guard : guard ,
96
- Direction : 0 , // This means north
97
- ObstacleMap : obstacles ,
98
- VisitedMap : visitedMap ,
144
+ Guard : guard ,
145
+ Direction : 0 , // This means north
146
+ ObstacleMatrix : obstacles ,
147
+ VisitedMap : visitedMap ,
99
148
}
100
- out .markVisited (guard )
149
+ out .checkIfVisitedAndMark (guard )
101
150
102
151
return out , nil
103
152
}
104
153
105
- // Move and return a boolean indicating whether the guard is inside the matrix or not
106
- func (
107
- p * parsedInput ,
108
- ) move () bool {
154
+ // Move and return a boolean indicating whether the guard is stuck in a loop or inside the matrix
155
+ // True means he's stuck or out, false means he's inside on a non-visited spot.
156
+ func (p * parsedInput ) move () bool {
109
157
newPos := getNewPosition (p .Guard , p .Direction )
110
- isBlocked , err := p .ObstacleMap .Get (newPos .X , newPos .Y )
158
+ isBlocked , err := p .ObstacleMatrix .Get (newPos .X , newPos .Y )
111
159
if err != nil {
160
+ p .Guard = newPos
112
161
return false
113
162
} else if isBlocked {
114
163
p .rotate ()
115
- newPos = getNewPosition ( p . Guard , p . Direction )
164
+ return ! p . checkIfVisitedAndMark ( p . Guard )
116
165
}
117
166
p .Guard = newPos
118
- if ! p .ObstacleMap .IsInMatrix (p .Guard .X , p .Guard .Y ) {
167
+
168
+ if p .checkIfVisitedAndMark (newPos ) {
119
169
return false
120
170
}
121
171
122
- p .markVisited (newPos )
123
172
return true
124
173
}
125
174
126
- func (p * parsedInput ) markVisited (
127
- c Coordinate ,
128
- ) {
175
+ func (p * parsedInput ) guardIsInMatrix () bool {
176
+ return p .ObstacleMatrix .IsInMatrix (p .Guard .X , p .Guard .Y )
177
+ }
178
+
179
+ func (p * parsedInput ) checkIfVisitedAndMark (c Coordinate ) bool {
129
180
if p .VisitedMap [c .X ] == nil {
130
181
p .VisitedMap [c .X ] = make (map [int ]map [int ]bool )
131
182
}
132
183
if p.VisitedMap [c.X ][c.Y ] == nil {
133
184
p.VisitedMap [c.X ][c.Y ] = make (map [int ]bool )
134
185
}
186
+ old := p.VisitedMap [c.X ][c.Y ][p .Direction ]
135
187
p.VisitedMap [c.X ][c.Y ][p .Direction ] = true
188
+ return old
136
189
}
137
190
138
191
func (p * parsedInput ) rotate () {
0 commit comments