adventofcode/2023/day16/main.go

125 lines
2.3 KiB
Go
Raw Normal View History

2023-12-16 16:17:04 +00:00
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))
}
}