125 lines
2.3 KiB
Go
125 lines
2.3 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
inp := h.StdinToStringSlice()
|
||
|
part1(inp)
|
||
|
fmt.Println()
|
||
|
part2(inp)
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
N = h.Coordinate{X: 0, Y: -1}
|
||
|
E = h.Coordinate{X: 1, Y: 0}
|
||
|
S = h.Coordinate{X: 0, Y: 1}
|
||
|
W = h.Coordinate{X: -1, Y: 0}
|
||
|
)
|
||
|
|
||
|
// movement describes how a beam moving in a direction should react
|
||
|
// to a byte
|
||
|
var movement = map[h.Coordinate]map[byte][]h.Coordinate{
|
||
|
N: {
|
||
|
'|': {N},
|
||
|
'-': {W, E},
|
||
|
'\\': {W},
|
||
|
'/': {E},
|
||
|
'.': {N},
|
||
|
},
|
||
|
E: {
|
||
|
'|': {N, S},
|
||
|
'-': {E},
|
||
|
'\\': {S},
|
||
|
'/': {N},
|
||
|
'.': {E},
|
||
|
},
|
||
|
S: {
|
||
|
'|': {S},
|
||
|
'-': {W, E},
|
||
|
'\\': {E},
|
||
|
'/': {W},
|
||
|
'.': {S},
|
||
|
},
|
||
|
W: {
|
||
|
'|': {N, S},
|
||
|
'-': {W},
|
||
|
'\\': {N},
|
||
|
'/': {S},
|
||
|
'.': {W},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
var tileHistory map[h.Coordinate][]h.Coordinate
|
||
|
|
||
|
func part1(input []string) {
|
||
|
mm := h.StringSliceToCoordByteMap(input)
|
||
|
tileHistory = make(map[h.Coordinate][]h.Coordinate)
|
||
|
proc(&mm, E, h.Coordinate{X: 0, Y: 0})
|
||
|
|
||
|
fmt.Println("# Part 1")
|
||
|
fmt.Println(len(tileHistory))
|
||
|
}
|
||
|
|
||
|
func part2(input []string) {
|
||
|
mm := h.StringSliceToCoordByteMap(input)
|
||
|
|
||
|
maxTiles := h.MIN_INT
|
||
|
// starts are a map of positions -> directions to test as a starting point
|
||
|
starts := make(map[*h.Coordinate]h.Coordinate)
|
||
|
for y := mm.TLY; y <= mm.BRY; y++ {
|
||
|
for x := mm.TLX; x <= mm.BRX; x++ {
|
||
|
if y != mm.TLY && x != mm.TLX && y != mm.BRY && x != mm.BRX {
|
||
|
continue
|
||
|
}
|
||
|
if y == mm.TLY {
|
||
|
// South facing beams
|
||
|
starts[&h.Coordinate{Y: y, X: x}] = S
|
||
|
} else if y == mm.BRY {
|
||
|
// North facing beams
|
||
|
starts[&h.Coordinate{Y: y, X: x}] = N
|
||
|
}
|
||
|
if x == mm.TLX {
|
||
|
// East facing beams
|
||
|
starts[&h.Coordinate{Y: y, X: x}] = E
|
||
|
}
|
||
|
if x == mm.BRX {
|
||
|
// West facing beams
|
||
|
starts[&h.Coordinate{Y: y, X: x}] = W
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for pos, dir := range starts {
|
||
|
tileHistory = make(map[h.Coordinate][]h.Coordinate)
|
||
|
proc(&mm, dir, *pos)
|
||
|
if len(tileHistory) > maxTiles {
|
||
|
maxTiles = len(tileHistory)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fmt.Println("# Part 2")
|
||
|
fmt.Println(maxTiles)
|
||
|
}
|
||
|
|
||
|
func proc(mm *h.CoordByteMap, dir, pos h.Coordinate) {
|
||
|
if !mm.ContainsCoord(pos) {
|
||
|
return
|
||
|
}
|
||
|
if visits, ok := tileHistory[pos]; ok {
|
||
|
for _, v := range visits {
|
||
|
if v == dir {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
curr := mm.Get(pos)
|
||
|
tileHistory[pos] = append(tileHistory[pos], dir)
|
||
|
next := movement[dir][curr]
|
||
|
for _, n := range next {
|
||
|
proc(mm, n, pos.Add(n))
|
||
|
}
|
||
|
}
|