package main import ( "bufio" _ "embed" "fmt" aoc "go.sour.is/advent-of-code" ) // var log = aoc.Log func main() { aoc.MustResult(aoc.Runner(runner(64))) } type result struct { valuePT1 int valuePT2 int } func (r result) String() string { return fmt.Sprintf("%#v", r) } func runner(rounds int) func(scan *bufio.Scanner) (*result, error) { return func(scan *bufio.Scanner) (*result, error) { var garden garden for scan.Scan() { txt := scan.Text() garden.m = append(garden.m, []rune(txt)) for i, c := range txt { if c == 'S' { garden.start[0] = len(garden.m) - 1 garden.start[1] = i } } } garden.Step(rounds) return &result{ valuePT1: len(garden.steps[len(garden.steps)-1]), }, nil } } type garden struct { start aoc.Point[int] m [][]rune steps []aoc.Set[aoc.Point[int]] } func (g *garden) Neighbors(p aoc.Point[int]) []aoc.Point[int] { var neighbors []aoc.Point[int] for _, n := range []aoc.Point[int]{ {p[0] - 1, p[1]}, {p[0] + 1, p[1]}, {p[0], p[1] - 1}, {p[0], p[1] + 1}, } { if n[0] >= 0 && n[0] < len(g.m) && n[1] >= 0 && n[1] < len(g.m[0]) && g.m[n[0]][n[1]] != '#' { neighbors = append(neighbors, n) } } return neighbors } func (g *garden) Step(n int) { if len(g.steps) == 0 { g.steps = append(g.steps, aoc.NewSet(g.start)) } for step := range(n) { g.steps = append(g.steps, aoc.NewSet[aoc.Point[int]]()) for p := range g.steps[step] { for _, n := range g.Neighbors(p) { g.steps[step+1].Add(n) } } } } func (g garden) String() string { var b []rune for i, line := range g.m { if i == g.start[0] { line[g.start[1]] = 'X' } if steps := len(g.steps) - 1; steps > 0 { for p := range g.steps[len(g.steps)-1] { if p[0] == i { line[p[1]] = 'O' } } } b = append(b, line...) b = append(b, '\n') } return string(b) }