From b0c161669e044a8abbe636bf9a1391df1c711e3b Mon Sep 17 00:00:00 2001 From: James Griffin Date: Sat, 11 Dec 2021 16:32:12 +0000 Subject: [PATCH] Day 11 solution --- README.md | 9 +++ eleven/cavern.go | 131 ++++++++++++++++++++++++++++++++++++++++++ eleven/cavern_test.go | 68 ++++++++++++++++++++++ eleven/input.txt | 10 ++++ eleven/main.go | 24 ++++++++ eleven/test_input.txt | 10 ++++ main.go | 3 + 7 files changed, 255 insertions(+) create mode 100644 eleven/cavern.go create mode 100644 eleven/cavern_test.go create mode 100644 eleven/input.txt create mode 100644 eleven/main.go create mode 100644 eleven/test_input.txt diff --git a/README.md b/README.md index 6b49c71..9a36a65 100644 --- a/README.md +++ b/README.md @@ -111,3 +111,12 @@ The solution for "ten" is: The syntax error score is 323613 The autoComplete score is 3103006161 ``` + +### Day eleven + +```sh +$ ./aoc2021 --eleven +The solution for "eleven" is: +There were 1669 flashes after 100 steps +They all flash on step 351 +``` diff --git a/eleven/cavern.go b/eleven/cavern.go new file mode 100644 index 0000000..e7f3ce6 --- /dev/null +++ b/eleven/cavern.go @@ -0,0 +1,131 @@ +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 +} diff --git a/eleven/cavern_test.go b/eleven/cavern_test.go new file mode 100644 index 0000000..b6af4ac --- /dev/null +++ b/eleven/cavern_test.go @@ -0,0 +1,68 @@ +package eleven + +import ( + "testing" +) + +func Test_read(t *testing.T) { + c := cavern{} + if err := c.load("test_input.txt"); err != nil { + t.Log(err) + t.FailNow() + } + + if len(c.octopodes) != 10 { + t.Logf("Expected 10 rows, found %d", len(c.octopodes)) + t.Fail() + } + + if len(c.octopodes[0]) != 10 { + t.Logf("Expected 10 columns, found %d", len(c.octopodes)) + t.Fail() + } +} + +func Test_flashes(t *testing.T) { + c := cavern{} + c.load("test_input.txt") + + flashes := c.totalFlashes(1) + + if flashes != 0 { + t.Logf("Expected 0 flashes, got %d", flashes) + t.Fail() + } + + flashes = c.totalFlashes(2) + + if flashes != 35 { + t.Logf("Expected 35 flashes, got %d", flashes) + t.Fail() + } + + flashes = c.totalFlashes(10) + + if flashes != 204 { + t.Logf("Expected 204 flashes, got %d", flashes) + t.Fail() + } + + flashes = c.totalFlashes(100) + + if flashes != 1656 { + t.Logf("Expected 1656 flashes, got %d", flashes) + t.Fail() + } +} + +func Test_stepsToSynchronousFlash(t *testing.T) { + c := cavern{} + c.load("test_input.txt") + + steps := c.stepsToSynchronousFlash() + + if steps != 195 { + t.Logf("Expected it to take 195 steps, found %d", steps) + t.Fail() + } +} diff --git a/eleven/input.txt b/eleven/input.txt new file mode 100644 index 0000000..a2f9f5b --- /dev/null +++ b/eleven/input.txt @@ -0,0 +1,10 @@ +6788383436 +5526827441 +4582435866 +5152547273 +3746433621 +2465145365 +6324887128 +8537558745 +4718427562 +2283324746 \ No newline at end of file diff --git a/eleven/main.go b/eleven/main.go new file mode 100644 index 0000000..dd4545b --- /dev/null +++ b/eleven/main.go @@ -0,0 +1,24 @@ +package eleven + +import "fmt" + +type Eleven struct { + cavern cavern +} + +func Init(filepath string) *Eleven { + eleven := &Eleven{ + cavern: cavern{}, + } + + eleven.cavern.load(filepath) + return eleven +} + +func (d *Eleven) Answer() string { + return fmt.Sprintf("There were %d flashes after 100 steps", d.cavern.totalFlashes(100)) +} + +func (d *Eleven) FollowUp() string { + return fmt.Sprintf("They all flash on step %d", d.cavern.stepsToSynchronousFlash()) +} diff --git a/eleven/test_input.txt b/eleven/test_input.txt new file mode 100644 index 0000000..a3819c9 --- /dev/null +++ b/eleven/test_input.txt @@ -0,0 +1,10 @@ +5483143223 +2745854711 +5264556173 +6141336146 +6357385478 +4167524645 +2176841721 +6882881134 +4846848554 +5283751526 \ No newline at end of file diff --git a/main.go b/main.go index 8d7137f..9245674 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "strings" "unsupervised.ca/aoc2021/eight" + "unsupervised.ca/aoc2021/eleven" "unsupervised.ca/aoc2021/five" "unsupervised.ca/aoc2021/four" "unsupervised.ca/aoc2021/nine" @@ -52,6 +53,8 @@ func main() { day = nine.Init("nine/input.txt") case "ten": day = ten.Init("ten/input.txt") + case "eleven": + day = eleven.Init("eleven/input.txt") default: fmt.Printf("%q does not have a solution.\n", flagParts[1]) help()