Created
December 21, 2021 11:47
-
-
Save r3domfox/635e8ec9a90f79725d3dcd86734162ac to your computer and use it in GitHub Desktop.
AOC2021 Day 20 (Python)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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