2021 day11: fun game of life ish thing

This commit is contained in:
alexchao26
2021-12-11 12:29:05 -05:00
parent 46d1c4a5a9
commit f32239d2cb
2 changed files with 179 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
package main
import (
_ "embed"
"flag"
"fmt"
"math"
"strings"
"github.com/alexchao26/advent-of-code-go/cast"
"github.com/alexchao26/advent-of-code-go/util"
)
//go:embed input.txt
var input string
func init() {
// do this in init (not main) so test file has same input
input = strings.TrimRight(input, "\n")
if len(input) == 0 {
panic("empty input.txt file")
}
}
func main() {
var part int
flag.IntVar(&part, "part", 1, "part 1 or 2")
flag.Parse()
fmt.Println("Running part", part)
ans := flashingOctopiLol(input, part)
util.CopyToClipboard(fmt.Sprintf("%v", ans))
fmt.Println("Output:", ans)
}
func flashingOctopiLol(input string, part int) int {
grid := parseInput(input)
var flashed int
adjacentDiffs := [][2]int{
{-1, 0},
{-1, -1},
{-1, 1},
{0, -1},
{0, 1},
{1, -1},
{1, 0},
{1, 1},
}
steps := 100
if part == 2 {
// assume it'll run in less steps than 2^31-1...
steps = math.MaxInt32
}
for s := 0; s < steps; s++ {
// initial increment and store who will flash
var queueToFlash [][2]int
for i, row := range grid {
for j := range row {
grid[i][j]++
if grid[i][j] > 9 {
queueToFlash = append(queueToFlash, [2]int{i, j})
}
}
}
// map tracks who has flashed, bc it's a map it'll also help dedupe and its length will be
// how many flashed on this step
seen := map[[2]int]bool{}
for len(queueToFlash) > 0 {
front := queueToFlash[0]
queueToFlash = queueToFlash[1:]
if seen[front] {
continue
}
seen[front] = true
// increment neighbors
for _, d := range adjacentDiffs {
r, c := front[0]+d[0], front[1]+d[1]
// check in bounds
if r < 0 || r >= len(grid) || c < 0 || c >= len(grid[0]) {
continue
}
grid[r][c]++
// check if neighbor should flash, seen map will dedupe so don't safeguard here
if grid[r][c] > 9 {
queueToFlash = append(queueToFlash, [2]int{r, c})
}
}
}
// part1, track how many have flashed in total
flashed += len(seen)
// set them all to zero
for c := range seen {
grid[c[0]][c[1]] = 0
}
// if all octopi flashed, return the step number (1-indexed)
if part == 2 && len(seen) == len(grid)*len(grid[0]) {
return s + 1
}
}
// for part 1
return flashed
}
func parseInput(input string) (ans [][]int) {
for _, line := range strings.Split(input, "\n") {
var row []int
for _, char := range strings.Split(line, "") {
row = append(row, cast.ToInt(char))
}
ans = append(ans, row)
}
return ans
}
+57
View File
@@ -0,0 +1,57 @@
package main
import (
"testing"
)
var example = `5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526`
func Test_flashingOctopiLol(t *testing.T) {
tests := []struct {
name string
input string
part int
want int
}{
{
name: "example",
input: example,
part: 1,
want: 1656,
},
{
name: "actual",
input: input,
part: 1,
want: 1723,
},
{
name: "example",
input: example,
part: 2,
want: 195,
},
{
name: "actual",
input: input,
part: 2,
want: 327,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := flashingOctopiLol(tt.input, tt.part); got != tt.want {
t.Errorf("flashingOctopiLol() = %v, want %v", got, tt.want)
}
})
}
}