Skip to content

Instantly share code, notes, and snippets.

@r3domfox
Created December 21, 2021 11:47
Show Gist options
  • Save r3domfox/635e8ec9a90f79725d3dcd86734162ac to your computer and use it in GitHub Desktop.
Save r3domfox/635e8ec9a90f79725d3dcd86734162ac to your computer and use it in GitHub Desktop.
AOC2021 Day 20 (Python)
def read_file(file):
i = iter(line.strip() for line in file)
algo = [c == '#' for c in next(i)]
assert len(algo) == 512
assert next(i) == ''
grid = set((x, y) for y, line in enumerate(i) for x, c in enumerate(line) if c == '#')
return algo, grid
def adjacent(coord):
x, y = coord
for ay in range(y - 1, y + 2):
for ax in range(x - 1, x + 2):
yield ax, ay
def lookup(algo, grid, outside_is_lit, outer_bounds, coord):
min_x, max_x, min_y, max_y = outer_bounds
def is_lit(c):
if c in grid:
return True
if not outside_is_lit:
return False
x, y = c
return x <= min_x or x >= max_x or y<= min_y or y >= max_y
digits = ('1' if is_lit(a) else '0'
for a in adjacent(coord))
lookup_index = int(str.join('', digits), 2)
return algo[lookup_index]
def bounds(grid):
min_x = min(x for (x, _) in grid)
max_x = max(x for (x, _) in grid)
min_y = min(y for (_, y) in grid)
max_y = max(y for (_, y) in grid)
return min_x, max_x, min_y, max_y
def expand_bounds(bounds):
min_x, max_x, min_y, max_y = bounds
return min_x - 1, max_x + 1, min_y - 1, max_y + 1
def next_gen(algo, grid, gen_number):
expanded_bounds = expand_bounds(bounds(grid))
min_x, max_x, min_y, max_y = expanded_bounds
outside_is_lit = gen_number % 2 == 1 and algo[0]
return set((x, y) for x in range(min_x, max_x + 1)
for y in range(min_y, max_y + 1)
if lookup(algo, grid, outside_is_lit, expanded_bounds, (x, y)))
def pretty_print(grid):
min_x, max_x, min_y, max_y = bounds(grid)
return str.join('\n',
(str.join("", ('#' if (x, y) in grid else '.'
for x in range(min_x, max_x + 1)))
for y in range(min_y, max_y + 1)))
def test_apply_algo():
example_algo_str = """
..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..##
#..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###
.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#.
.#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#.....
.#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#..
...####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.....
..##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
"""
example_algo = [c == '#' for c in str.join('', (line.strip() for line in example_algo_str.split('\n')))]
example_grid_str = """
#..#.
#....
##..#
..#..
..###
"""
example_grid = set((x, y) for y, line in enumerate(example_grid_str.strip().split('\n'))
for x, c in enumerate(line.strip()) if c == '#')
print()
print(pretty_print(example_grid))
print()
print(pretty_print(g2 := next_gen(example_algo, example_grid, 0)))
print()
print(pretty_print(g3 := next_gen(example_algo, g2, 1)))
assert len(g3) == 35
with open('puzzle_inputs/day20.txt') as file:
algo, grid = read_file(file)
print()
g = grid
for i in range(2):
g = next_gen(algo, g, i)
print()
print(len(g))
for i in range(48):
g = next_gen(algo, g, i)
print(len(g))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment