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 }