132 lines
2.3 KiB
Go
132 lines
2.3 KiB
Go
package eleven
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type cavern struct {
|
|
octopodes [][]int
|
|
}
|
|
|
|
func (c *cavern) load(filename string) error {
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
energies := strings.Split(scanner.Text(), "")
|
|
|
|
row := []int{}
|
|
for _, e := range energies {
|
|
v, err := strconv.Atoi(e)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
row = append(row, v)
|
|
}
|
|
c.octopodes = append(c.octopodes, row)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *cavern) copyOctopodes() [][]int {
|
|
copy := make([][]int, 10)
|
|
for i := range copy {
|
|
copy[i] = make([]int, 10)
|
|
}
|
|
|
|
for y := 0; y < 10; y++ {
|
|
for x := 0; x < 10; x++ {
|
|
copy[y][x] = c.octopodes[y][x]
|
|
}
|
|
}
|
|
|
|
return copy
|
|
}
|
|
|
|
func (c *cavern) stepsToSynchronousFlash() int {
|
|
flashes := 0
|
|
steps := 1
|
|
for {
|
|
flashes = c.flashes(c.octopodes, 1)
|
|
if flashes == 100 {
|
|
return steps
|
|
}
|
|
steps++
|
|
}
|
|
}
|
|
|
|
func (c *cavern) totalFlashes(steps int) int {
|
|
current := c.copyOctopodes()
|
|
|
|
return c.flashes(current, steps)
|
|
}
|
|
|
|
func (c *cavern) flashes(current [][]int, steps int) int {
|
|
flashes := 0
|
|
|
|
for step := 0; step < steps; step++ {
|
|
newFlashes := 0
|
|
// increase energy
|
|
for y := 0; y < 10; y++ {
|
|
for x := 0; x < 10; x++ {
|
|
current[y][x]++
|
|
|
|
if current[y][x] > 9 {
|
|
newFlashes++
|
|
}
|
|
}
|
|
}
|
|
|
|
// increase neighbours
|
|
flashed := map[string]bool{}
|
|
for newFlashes != 0 {
|
|
newFlashes = 0
|
|
for y := 0; y < 10; y++ {
|
|
for x := 0; x < 10; x++ {
|
|
key := fmt.Sprintf("%d%d", x, y)
|
|
if current[y][x] > 9 && !flashed[key] {
|
|
flashed[key] = true
|
|
for flashY := y - 1; flashY <= y+1; flashY++ {
|
|
for flashX := x - 1; flashX <= x+1; flashX++ {
|
|
flashKey := fmt.Sprintf("%d%d", flashX, flashY)
|
|
|
|
if flashY == y && flashX == x {
|
|
continue
|
|
}
|
|
|
|
// Check boundaries
|
|
if flashY >= 0 && flashY < 10 && flashX >= 0 && flashX < 10 {
|
|
current[flashY][flashX]++
|
|
if current[flashY][flashX] > 9 && !flashed[flashKey] {
|
|
newFlashes++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// zero out flashed
|
|
for y := 0; y < 10; y++ {
|
|
for x := 0; x < 10; x++ {
|
|
if current[y][x] > 9 {
|
|
flashes++
|
|
current[y][x] = 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return flashes
|
|
}
|