My Advent of Code solutions in Python. kevinyap.ca/2019/12/going-fast-in-advent-of-code/
advent-of-code python
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Optimize 2017/day21.py

After 3 iterations, a 3x3 grid is transformed into a 9x9 grid, whose
component 3x3 grids can be treated separately from that point on.
Instead of building the full grid (which grows exponentially), store a
count of each 3x3 "subgrid" and operate on each of them independently.

+51 -26
+51 -26
2017/day21.py
··· 1 1 import fileinput 2 + from collections import Counter 3 + 2 4 from utils import new_table 3 5 4 6 5 7 def lit_pixels(grid): 6 8 return sum(sum(c == '#' for c in row) for row in grid) 7 9 8 - 9 - GRID = [ 10 - ['.', '#', '.'], 11 - ['.', '.', '#'], 12 - ['#', '#', '#'], 13 - ] 14 10 15 11 RULES = {} 16 12 ··· 34 30 35 31 grid = rotated 36 32 37 - for i in range(18): 38 - size = len(GRID[0]) 39 - d = 2 if size % 2 == 0 else 3 33 + SUBGRIDS = Counter() 34 + SUBGRIDS['.#...####'] += 1 35 + 36 + for it in range(18): 37 + # Build up our list of subgrids 38 + if it % 3 == 0: 39 + GRIDS = [] 40 + ORIG_GRIDS = [] 41 + for inp in SUBGRIDS: 42 + GRIDS.append([list(inp[n:n+3]) for n in range(0, 9, 3)]) 43 + ORIG_GRIDS.append(inp) 44 + 45 + NEW_GRIDS = [] 46 + for grid in GRIDS: 47 + size = len(grid) 48 + d = 2 if size % 2 == 0 else 3 49 + 50 + new_size = (size // d) * (d + 1) 51 + new_grid = new_table(None, width=new_size, height=new_size) 52 + 53 + for y in range(size // d): 54 + for x in range(size // d): 55 + # Build the string representation of each 2x2 or 3x3 subgrid 56 + subgrid = '' 40 57 41 - new_size = (size // d) * (d + 1) 42 - new_grid = new_table(None, width=new_size, height=new_size) 58 + for k in range(d): 59 + subgrid += ''.join(grid[y*d + k][x*d:(x+1)*d]) 43 60 44 - for y in range(size // d): 45 - for x in range(size // d): 46 - # Build the string representation of each 2x2 or 3x3 subgrid 47 - subgrid = '' 61 + # Lookup the corresponding rule and populate the new grid 62 + out = RULES[subgrid] 63 + for ny in range(d+1): 64 + for nx in range(d+1): 65 + new_grid[y*(d+1) + ny][x*(d+1) + nx] = out[ny*(d+1) + nx] 48 66 49 - for k in range(d): 50 - subgrid += ''.join(GRID[y*d + k][x*d:(x+1)*d]) 67 + NEW_GRIDS.append(new_grid) 51 68 52 - # Lookup the corresponding rule and populate the new grid 53 - out = RULES[subgrid] 54 - for ny in range(d+1): 55 - for nx in range(d+1): 56 - new_grid[y*(d+1) + ny][x*(d+1) + nx] = out[ny*(d+1) + nx] 69 + GRIDS = NEW_GRIDS 57 70 58 - GRID = new_grid 71 + if it in (4, 17): 72 + num_pixels = sum(lit_pixels(g) * SUBGRIDS[ORIG_GRIDS[i]] for i, g in enumerate(GRIDS)) 73 + print "Lit pixels after {} iterations:".format(it + 1), num_pixels 59 74 60 - if i == 4: 61 - print "Lit pixels after 5 iterations:", lit_pixels(GRID) 75 + # Update the count of independent 3x3 subgrids 76 + if it % 3 == 2: 77 + next_subgrids = Counter() 78 + for i, grid in enumerate(GRIDS): 79 + mult = SUBGRIDS[ORIG_GRIDS[i]] 80 + for y in range(0, 9, 3): 81 + for x in range(0, 9, 3): 82 + key = ''.join( 83 + ''.join(grid[y+n][x:x+3]) 84 + for n in range(3) 85 + ) 86 + next_subgrids[key] += mult 62 87 63 - print "Lit pixels after 18 iterations:", lit_pixels(GRID) 88 + SUBGRIDS = next_subgrids