From 0a6d8ab25610430af5fc211c3c087f321bc41c5e Mon Sep 17 00:00:00 2001 From: Parnic Date: Sun, 26 Jun 2022 19:44:06 -0500 Subject: [PATCH] Day 24 part 2 This isn't terribly slow (100ms right now) but I'd prefer it to be faster. I'm sure I could be smarter about which depths I'm scanning since a bunch of them can't possibly contain bugs, but whatever. This was about as rote and straightforward as I was expecting it to be, so at least there's that. --- days/24.go | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 2 deletions(-) diff --git a/days/24.go b/days/24.go index 84b74d9..2c848fd 100644 --- a/days/24.go +++ b/days/24.go @@ -51,6 +51,96 @@ func (d Day24) calcActivatedNeighbors(grid [][]bool, i, j int) int { return activatedNeighbors } +func (d Day24) recursiveCalcActivatedNeighbors(gridMap map[int][][]bool, mapIdx, i, j int) int { + activatedNeighbors := 0 + numNeighbors := 0 + thisGrid := gridMap[mapIdx] + for _, o := range day24AdjacentOffsets { + newI := i + o.X + newJ := j + o.Y + if newI < 0 || newI >= len(thisGrid) || newJ < 0 || newJ >= len(thisGrid[i]) { + continue + } + if newI == 2 && newJ == 2 { + continue + } + numNeighbors++ + if thisGrid[newI][newJ] { + activatedNeighbors++ + } + } + + checkLower := (i == 1 && j == 2) || + (i == 2 && (j == 1 || j == 3)) || + (i == 3 && j == 2) + if checkLower { + if lowerGrid, exists := gridMap[mapIdx+1]; exists { + if i == 1 { + for _, b := range lowerGrid[0] { + numNeighbors++ + if b { + activatedNeighbors++ + } + } + } else if i == 2 { + if j == 1 { + for _, r := range lowerGrid { + numNeighbors++ + if r[0] { + activatedNeighbors++ + } + } + } else if j == 3 { + for _, r := range lowerGrid { + numNeighbors++ + if r[len(lowerGrid[0])-1] { + activatedNeighbors++ + } + } + } + } else if i == 3 { + for _, b := range lowerGrid[len(lowerGrid)-1] { + numNeighbors++ + if b { + activatedNeighbors++ + } + } + } + } + } + + checkUpper := (i == 0) || (i == len(thisGrid)-1) || + ((i != 0 && i != len(thisGrid)) && (j == 0 || j == len(thisGrid[0])-1)) + if checkUpper { + if upperGrid, exists := gridMap[mapIdx-1]; exists { + if i == 0 { + numNeighbors++ + if upperGrid[1][2] { + activatedNeighbors++ + } + } else if i == len(thisGrid)-1 { + numNeighbors++ + if upperGrid[3][2] { + activatedNeighbors++ + } + } + if j == 0 { + numNeighbors++ + if upperGrid[2][1] { + activatedNeighbors++ + } + } else if j == len(thisGrid[0])-1 { + numNeighbors++ + if upperGrid[2][3] { + activatedNeighbors++ + } + } + } + } + + return activatedNeighbors +} + func (d Day24) calcRating(grid [][]bool) int { rating := 0 for i, r := range grid { @@ -65,6 +155,20 @@ func (d Day24) calcRating(grid [][]bool) int { return rating } +func (d Day24) numBugs(gridMap map[int][][]bool) int { + ret := 0 + for _, v := range gridMap { + for _, r := range v { + for _, b := range r { + if b { + ret++ + } + } + } + } + return ret +} + func copy2d[T comparable](dest [][]T, src [][]T) { for i, r := range src { copy(dest[i], r) @@ -113,7 +217,7 @@ func (d *Day24) Part1() string { rating := d.calcRating(scratch) if u.ArrayContains(seenRatings, rating) { found = true - d.Draw(scratch) + // d.Draw(scratch) answer = rating } seenRatings = append(seenRatings, rating) @@ -124,5 +228,62 @@ func (d *Day24) Part1() string { } func (d *Day24) Part2() string { - return fmt.Sprintf("%s%d%s", u.TextBold, 0, u.TextReset) + makeGrid := func(initialGrid [][]bool) ([][]bool, [][]bool) { + grid := make([][]bool, len(d.grid)) + scratch := make([][]bool, len(grid)) + for i, g := range d.grid { + grid[i] = make([]bool, len(g)) + scratch[i] = make([]bool, len(g)) + if initialGrid != nil { + copy(grid[i], initialGrid[i]) + } + } + + return grid, scratch + } + + gridMap := make(map[int][][]bool) + scratchMap := make(map[int][][]bool) + gridMap[0], scratchMap[0] = makeGrid(d.grid) + + min := 0 + max := 0 + + for i := 0; i < 200; i++ { + gridMap[min-1], scratchMap[min-1] = makeGrid(nil) + gridMap[max+1], scratchMap[max+1] = makeGrid(nil) + min, max = min-1, max+1 + + // if i == 10 { + // keys := u.MapKeys(gridMap) + // sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] }) + // for _, k := range keys { + // fmt.Println("Depth", k) + // d.Draw(gridMap[k]) + // } + // fmt.Println("# bugs:", d.numBugs(gridMap)) + // } + + for depth, grid := range gridMap { + for i, r := range grid { + for j := range r { + if i == 2 && j == 2 { + continue + } + numActivated := d.recursiveCalcActivatedNeighbors(gridMap, depth, i, j) + if grid[i][j] { + scratchMap[depth][i][j] = numActivated == 1 + } else { + scratchMap[depth][i][j] = numActivated == 1 || numActivated == 2 + } + } + } + } + + for d := range gridMap { + copy2d(gridMap[d], scratchMap[d]) + } + } + + return fmt.Sprintf("Bugs present after 200 minutes: %s%d%s", u.TextBold, d.numBugs(gridMap), u.TextReset) }