summaryrefslogtreecommitdiffstats
path: root/20/py
diff options
context:
space:
mode:
Diffstat (limited to '20/py')
-rw-r--r--20/py/d17.py90
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))