Day 17, any dimensions you want!

This commit is contained in:
dece 2020-12-17 18:48:54 +01:00
parent ae2ddfc742
commit 94f8d2f443

View file

@ -1,18 +1,20 @@
import sys import sys
from itertools import product
def main(): def main():
lines = [line.rstrip() for line in sys.stdin]; sys.stdin = open("/dev/tty") lines = [line.rstrip() for line in sys.stdin]
print("Actives:", part1(lines)) print("Actives:", solve(lines, 3))
print("Hyperactives:", part2(lines)) print("Hyperactives:", solve(lines, 4))
def part1(lines): def solve(lines, dimensions):
s = {} s = {}
for y, line in enumerate(lines): for y, line in enumerate(lines):
for x, c in enumerate(line): for x, c in enumerate(line):
s[(x, y, 0)] = 1 if c == "#" else 0 p = (x, y) + (0,) * (dimensions - 2)
s[p] = 1 if c == "#" else 0
for _ in range(6): for _ in range(6):
cycle(s) cycle(s)
return sum(s.values()) return sum(s.values())
@ -20,59 +22,25 @@ def part1(lines):
def cycle(s): def cycle(s):
future = {} future = {}
work_set = set(nn for x, y, z in s for nn in near(x, y, z)) work_set = set(nn for pos in s for nn in near(*pos))
for x, y, z in work_set: for pos in work_set:
an = 0 an = 0
for nn in near(x, y, z): for nn in near(*pos):
an += s.get(nn, 0) an += s.get(nn, 0)
if (v := s.get((x, y, z), 0)) == 1 and not 2 <= an <= 3: if (v := s.get(pos, 0)) == 1 and not 2 <= an <= 3:
future[(x, y, z)] = 0 future[pos] = 0
elif v == 0 and an == 3: elif v == 0 and an == 3:
future[(x, y, z)] = 1 future[pos] = 1
for f, fv in future.items(): for f, fv in future.items():
s[f] = fv s[f] = fv
def near(x, y, z, include_self=False): def near(*comp):
for zi in range(-1, 2): num_comp = len(comp)
for yi in range(-1, 2): offsets = list(product([-1, 0, 1], repeat=num_comp))
for xi in range(-1, 2): offsets.remove((0,) * num_comp)
if include_self or xi != 0 or yi != 0 or zi != 0: for p in offsets:
yield x + xi, y + yi, z + zi yield tuple(c + o for c, o in zip(comp, p))
def part2(lines):
h = {}
for y, line in enumerate(lines):
for x, c in enumerate(line):
h[(x, y, 0, 0)] = 1 if c == "#" else 0
for _ in range(6):
cycle2(h)
return sum(h.values())
def cycle2(h):
future = {}
work_set = set(nn for x, y, z, w in h for nn in hyper_near(x, y, z, w))
for x, y, z, w in work_set:
an = 0
for nn in hyper_near(x, y, z, w):
an += h.get(nn, 0)
if (v := h.get((x, y, z, w), 0)) == 1 and not 2 <= an <= 3:
future[(x, y, z, w)] = 0
elif v == 0 and an == 3:
future[(x, y, z, w)] = 1
for f, fv in future.items():
h[f] = fv
def hyper_near(x, y, z, w, include_self=False): # oh boy
for wi in range(-1, 2):
for zi in range(-1, 2):
for yi in range(-1, 2):
for xi in range(-1, 2):
if include_self or xi != 0 or yi != 0 or zi != 0 or wi != 0:
yield x + xi, y + yi, z + zi, w + wi
if __name__ == "__main__": if __name__ == "__main__":