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)) } }