package days import ( "fmt" "math" u "parnic.com/aoc2019/utilities" ) var ( day24AdjacentOffsets = []u.Vec2i{ {X: -1, Y: 0}, {X: 1, Y: 0}, {X: 0, Y: -1}, {X: 0, Y: 1}, } ) type Day24 struct { grid [][]bool } func (d *Day24) Parse() { lines := u.GetStringLines("24p") d.grid = make([][]bool, len(lines)) for i, line := range lines { d.grid[i] = make([]bool, len(line)) for j, ch := range line { d.grid[i][j] = ch == '#' } } } func (d Day24) Num() int { return 24 } func (d Day24) calcActivatedNeighbors(grid [][]bool, i, j int) int { activatedNeighbors := 0 for _, o := range day24AdjacentOffsets { newI := i + o.X newJ := j + o.Y if newI < 0 || newI >= len(grid) || newJ < 0 || newJ >= len(grid[i]) { continue } if grid[newI][newJ] { activatedNeighbors++ } } return activatedNeighbors } func (d Day24) calcRating(grid [][]bool) int { rating := 0 for i, r := range grid { for j := range r { pow := (i * len(r)) + j if grid[i][j] { result := int(math.Pow(2, float64(pow))) rating += result } } } return rating } func copy2d[T comparable](dest [][]T, src [][]T) { for i, r := range src { copy(dest[i], r) } } func (d Day24) Draw(grid [][]bool) { for _, r := range grid { for _, c := range r { if c { fmt.Print("#") } else { fmt.Print(".") } } fmt.Println() } fmt.Println() } func (d *Day24) Part1() string { grid := make([][]bool, len(d.grid)) scratch := make([][]bool, len(grid)) for i, g := range d.grid { grid[i] = make([]bool, len(g)) scratch[i] = make([]bool, len(g)) copy(grid[i], d.grid[i]) } found := false answer := 0 seenRatings := make([]int, 0) for i := 1; !found; i++ { // d.Draw(grid) for i, r := range grid { for j := range r { numActivated := d.calcActivatedNeighbors(grid, i, j) if grid[i][j] { scratch[i][j] = numActivated == 1 } else { scratch[i][j] = numActivated == 1 || numActivated == 2 } } } rating := d.calcRating(scratch) if u.ArrayContains(seenRatings, rating) { found = true d.Draw(scratch) answer = rating } seenRatings = append(seenRatings, rating) copy2d(grid, scratch) } return fmt.Sprintf("First repeated biodiversity rating is %s%d%s", u.TextBold, answer, u.TextReset) } func (d *Day24) Part2() string { return fmt.Sprintf("%s%d%s", u.TextBold, 0, u.TextReset) }