|
@@ -44,76 +44,95 @@ const (
|
|
|
West
|
|
|
)
|
|
|
|
|
|
-type Beam struct {
|
|
|
+type Point struct {
|
|
|
y, x int
|
|
|
direction int
|
|
|
}
|
|
|
|
|
|
-func (b *Beam) canContinue(board [][]byte, height int, width int) []Beam {
|
|
|
+type Beam struct {
|
|
|
+ pos Point
|
|
|
+ wasHere map[Point]bool
|
|
|
+}
|
|
|
+
|
|
|
+func (b *Beam) canContinue(board [][]byte, height int, width int, pastBeams map[Point]bool) []Beam {
|
|
|
var beams []Beam
|
|
|
- if b.x < 0 || b.x >= width || b.y < 0 || b.y >= height {
|
|
|
+ if b.wasHere[b.pos] || b.pos.x < 0 || b.pos.x >= width || b.pos.y < 0 || b.pos.y >= height {
|
|
|
return beams
|
|
|
}
|
|
|
|
|
|
- switch board[b.y][b.x] {
|
|
|
+ switch board[b.pos.y][b.pos.x] {
|
|
|
case Horizontal:
|
|
|
- if b.direction != East && b.direction != West {
|
|
|
- b.direction = East
|
|
|
- beams = append(beams, *b)
|
|
|
- b.direction = West
|
|
|
- beams = append(beams, *b)
|
|
|
+ if b.pos.direction != East && b.pos.direction != West {
|
|
|
+ b.pos.direction = East
|
|
|
+ if !pastBeams[b.pos] {
|
|
|
+ pastBeams[b.pos] = true
|
|
|
+ beams = append(beams, *b)
|
|
|
+ }
|
|
|
+ b.pos.direction = West
|
|
|
+ if !pastBeams[b.pos] {
|
|
|
+ pastBeams[b.pos] = true
|
|
|
+ beams = append(beams, *b)
|
|
|
+ }
|
|
|
|
|
|
return beams
|
|
|
}
|
|
|
case Vertical:
|
|
|
- if b.direction != South && b.direction != North {
|
|
|
- b.direction = South
|
|
|
- beams = append(beams, *b)
|
|
|
- b.direction = North
|
|
|
- beams = append(beams, *b)
|
|
|
+ if b.pos.direction != South && b.pos.direction != North {
|
|
|
+ b.pos.direction = South
|
|
|
+ if !pastBeams[b.pos] {
|
|
|
+ pastBeams[b.pos] = true
|
|
|
+ beams = append(beams, *b)
|
|
|
+ }
|
|
|
+ b.pos.direction = North
|
|
|
+ if !pastBeams[b.pos] {
|
|
|
+ pastBeams[b.pos] = true
|
|
|
+ beams = append(beams, *b)
|
|
|
+ }
|
|
|
|
|
|
return beams
|
|
|
}
|
|
|
case Slash:
|
|
|
- switch b.direction {
|
|
|
+ switch b.pos.direction {
|
|
|
case North:
|
|
|
- b.direction = East
|
|
|
+ b.pos.direction = East
|
|
|
case South:
|
|
|
- b.direction = West
|
|
|
+ b.pos.direction = West
|
|
|
case East:
|
|
|
- b.direction = North
|
|
|
+ b.pos.direction = North
|
|
|
case West:
|
|
|
- b.direction = South
|
|
|
+ b.pos.direction = South
|
|
|
}
|
|
|
case Backslash:
|
|
|
- switch b.direction {
|
|
|
+ switch b.pos.direction {
|
|
|
case North:
|
|
|
- b.direction = West
|
|
|
+ b.pos.direction = West
|
|
|
case South:
|
|
|
- b.direction = East
|
|
|
+ b.pos.direction = East
|
|
|
case East:
|
|
|
- b.direction = South
|
|
|
+ b.pos.direction = South
|
|
|
case West:
|
|
|
- b.direction = North
|
|
|
+ b.pos.direction = North
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return append(beams, *b)
|
|
|
}
|
|
|
|
|
|
-func (b *Beam) move(board [][]byte, height int, width int) []Beam {
|
|
|
- switch b.direction {
|
|
|
+func (b *Beam) move(board [][]byte, height int, width int, pastBeams map[Point]bool) []Beam {
|
|
|
+ b.wasHere[b.pos] = true
|
|
|
+
|
|
|
+ switch b.pos.direction {
|
|
|
case North:
|
|
|
- b.y--
|
|
|
+ b.pos.y--
|
|
|
case South:
|
|
|
- b.y++
|
|
|
+ b.pos.y++
|
|
|
case East:
|
|
|
- b.x++
|
|
|
+ b.pos.x++
|
|
|
case West:
|
|
|
- b.x--
|
|
|
+ b.pos.x--
|
|
|
}
|
|
|
|
|
|
- return b.canContinue(board, height, width)
|
|
|
+ return b.canContinue(board, height, width, pastBeams)
|
|
|
}
|
|
|
|
|
|
func emptyBoard(height int, width int) [][]byte {
|
|
@@ -141,31 +160,29 @@ func count(board [][]byte) int {
|
|
|
func part1(board [][]byte) int {
|
|
|
height := len(board)
|
|
|
width := len(board[0])
|
|
|
- var result int
|
|
|
trackBoard := emptyBoard(height, width)
|
|
|
- beams := []Beam{Beam{y: 0, x: 0, direction: East}}
|
|
|
+ beams := []Beam{Beam{pos: Point{y: 0, x: 0, direction: East}, wasHere: make(map[Point]bool)}}
|
|
|
+ pastBeams := make(map[Point]bool)
|
|
|
+ pastBeams[beams[0].pos] = true
|
|
|
|
|
|
for {
|
|
|
- change := false
|
|
|
+ if len(beams) == 0 {
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
var newBeams []Beam
|
|
|
for i := range beams {
|
|
|
- if trackBoard[beams[i].y][beams[i].x] != Mark {
|
|
|
- trackBoard[beams[i].y][beams[i].x] = Mark
|
|
|
- change = true
|
|
|
+ if trackBoard[beams[i].pos.y][beams[i].pos.x] != Mark {
|
|
|
+ trackBoard[beams[i].pos.y][beams[i].pos.x] = Mark
|
|
|
}
|
|
|
|
|
|
- newBeams = append(newBeams, beams[i].move(board, height, width)...)
|
|
|
- }
|
|
|
-
|
|
|
- if !change {
|
|
|
- break
|
|
|
+ newBeams = append(newBeams, beams[i].move(board, height, width, pastBeams)...)
|
|
|
}
|
|
|
|
|
|
beams = newBeams
|
|
|
}
|
|
|
|
|
|
- fmt.Println(count(trackBoard), trackBoard)
|
|
|
- return result
|
|
|
+ return count(trackBoard)
|
|
|
}
|
|
|
|
|
|
func main() {
|
|
@@ -181,5 +198,5 @@ func main() {
|
|
|
}
|
|
|
|
|
|
board := readInput(file)
|
|
|
- fmt.Println(part1(board))
|
|
|
+ fmt.Println("Part1:", part1(board))
|
|
|
}
|