134 lines
2.2 KiB
Go
134 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/jdkaplan/advent-of-code/aoc"
|
|
)
|
|
|
|
func main() {
|
|
lines := aoc.Input().ReadLines("day11.txt")
|
|
fmt.Println(part1(lines))
|
|
fmt.Println(part2(lines))
|
|
}
|
|
|
|
func part1(lines []string) (flashes int) {
|
|
g := NewGrid(lines)
|
|
for i := 0; i < 100; i++ {
|
|
count := g.Tick()
|
|
flashes += count
|
|
}
|
|
return
|
|
}
|
|
|
|
func part2(lines []string) int {
|
|
g := NewGrid(lines)
|
|
all := g.Rows * g.Cols
|
|
for i := 0; true; i++ {
|
|
if g.Tick() == all {
|
|
return i + 1
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
type RC struct{ r, c int }
|
|
|
|
type Grid struct {
|
|
Rows int
|
|
Cols int
|
|
|
|
m map[RC]int
|
|
}
|
|
|
|
func NewGrid(lines []string) Grid {
|
|
g := Grid{
|
|
m: make(map[RC]int),
|
|
Rows: len(lines),
|
|
Cols: len(lines[0]),
|
|
}
|
|
for r, row := range lines {
|
|
for c, col := range row {
|
|
g.m[RC{r, c}] = int(col - '0')
|
|
}
|
|
}
|
|
return g
|
|
}
|
|
|
|
var red = color.New(color.FgRed)
|
|
|
|
func (g Grid) String() string {
|
|
var sb strings.Builder
|
|
for r := 0; r < g.Rows; r++ {
|
|
for c := 0; c < g.Cols; c++ {
|
|
if e := g.m[RC{r, c}]; e == 0 {
|
|
red.Fprintf(&sb, "%d", e)
|
|
} else {
|
|
fmt.Fprintf(&sb, "%d", e)
|
|
}
|
|
}
|
|
sb.WriteString("\n")
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
func (g Grid) Equal(o Grid) bool {
|
|
for r := 0; r < g.Rows; r++ {
|
|
for c := 0; c < g.Cols; c++ {
|
|
rc := RC{r, c}
|
|
if g.m[rc] != o.m[rc] {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (g *Grid) Tick() (flashes int) {
|
|
var frontier []RC
|
|
flashed := make(map[RC]bool)
|
|
for r := 0; r < g.Rows; r++ {
|
|
for c := 0; c < g.Cols; c++ {
|
|
rc := RC{r, c}
|
|
g.m[rc]++
|
|
if g.m[rc] > 9 {
|
|
frontier = append(frontier, rc)
|
|
}
|
|
}
|
|
}
|
|
|
|
for len(frontier) > 0 {
|
|
rc := frontier[0]
|
|
frontier = frontier[1:]
|
|
if flashed[rc] {
|
|
continue
|
|
}
|
|
for _, n := range g.Neighbors(rc) {
|
|
g.m[n]++
|
|
if g.m[n] > 9 {
|
|
frontier = append(frontier, n)
|
|
}
|
|
}
|
|
flashed[rc] = true
|
|
}
|
|
for rc := range flashed {
|
|
g.m[rc] = 0
|
|
}
|
|
return len(flashed)
|
|
}
|
|
|
|
func (g Grid) Neighbors(rc RC) (ns []RC) {
|
|
r, c := rc.r, rc.c
|
|
for _, n := range []RC{
|
|
{r - 1, c - 1}, {r - 1, c}, {r - 1, c + 1},
|
|
{r, c - 1}, {r, c + 1},
|
|
{r + 1, c - 1}, {r + 1, c}, {r + 1, c + 1},
|
|
} {
|
|
if 0 <= n.r && n.r < g.Rows && 0 <= n.c && n.c < g.Cols {
|
|
ns = append(ns, n)
|
|
}
|
|
}
|
|
return
|
|
}
|