diff options
Diffstat (limited to '20/py')
| -rw-r--r-- | 20/py/d17.py | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/20/py/d17.py b/20/py/d17.py new file mode 100644 index 0000000..5ec1419 --- /dev/null +++ b/20/py/d17.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +import aoc20 +import sys +import functools +from collections import defaultdict + + +@functools.cache +def neighbours3(p): + res = set() + for dx in range(-1, 1+1): + for dy in range(-1, 1+1): + for dz in range(-1, 1+1): + if dx == dy == dz == 0: + continue + res.add((p[0] + dx, p[1] + dy, p[2] + dz)) + return res + + +def pt1(_in): + active = set() + board = defaultdict(lambda: 0) + for y in range(len(_in)): + for x in range(len(_in[y])): + if _in[y][x] == "#": + active.add((x, y, 0)) + for n in neighbours3((x, y, 0)): + board[n] += 1 + + for _ in range(6): + new_board = defaultdict(lambda: 0) + new_active = set() + for p, deg in board.items(): + if p in active and 2 <= deg <= 3: + new_active.add(p) + for n in neighbours3(p): + new_board[n] += 1 + elif p not in active and deg == 3: + new_active.add(p) + for n in neighbours3(p): + new_board[n] += 1 + board = new_board + active = new_active + return(len(active)) + + +@functools.cache +def neighbours4(p): + res = set() + for dx in range(-1, 1+1): + for dy in range(-1, 1+1): + for dz in range(-1, 1+1): + for dw in range(-1, 1+1): + if dx == dy == dz == dw == 0: + continue + res.add((p[0] + dx, p[1] + dy, p[2] + dz, p[3] + dw)) + return res + + +def pt2(_in): + active = set() + board = defaultdict(lambda: 0) + for y in range(len(_in)): + for x in range(len(_in[y])): + if _in[y][x] == "#": + active.add((x, y, 0, 0)) + for n in neighbours4((x, y, 0, 0)): + board[n] += 1 + + for _ in range(6): + new_board = defaultdict(lambda: 0) + new_active = set() + for p, deg in board.items(): + if p in active and 2 <= deg <= 3: + new_active.add(p) + for n in neighbours4(p): + new_board[n] += 1 + elif p not in active and deg == 3: + new_active.add(p) + for n in neighbours4(p): + new_board[n] += 1 + board = new_board + active = new_active + return(len(active)) + + +if __name__ == "__main__": + input = aoc20.read_input(sys.argv[1:], 17) + print(pt1(input)) + print(pt2(input)) |
