advent2020/eleven.py

84 lines
2.6 KiB
Python
Executable File

#!/usr/bin/env python3
from functools import reduce
import re, sys
import sys
import numpy as np
empty, seat, occ = 0, 1, 2
def tpl(l): # get nice tuple from line
return [seat if x == 'L' else empty for x in l]
def pp(*args):
print(*args)
def p(image):
for y in range(image.shape[0]):
for x in range(image.shape[1]):
sys.stdout.write('.L#'[image[y][x]])
pp()
pp()
def frob(image):
padded = np.pad(image, 1)
sur = sum(padded[offy:offy+image.shape[0], offx:offx+image.shape[1]] == occ
for offy in range(3)
for offx in range(3)) - (image == occ)
# sod it
new = (occ if np.any(sur == 0) and np.any(image == seat) else
seat if np.any(sur >= 4) and np.any(image == occ) else
image)
new = np.zeros(image.shape, dtype=int)
for (y, x), c in np.ndenumerate(image):
new[y][x] = (occ if sur[y][x] == 0 and c == seat else
(seat if sur[y][x] >= 4 and c == occ else
c))
return new
def throb(image):
pads = max(image.shape)
padded = np.pad(image.astype('uint32'), ((pads, pads), (pads, pads)))
sur = np.zeros(image.shape, dtype=int)
for y in range(image.shape[0]):
for x in range(image.shape[1]):
for offy in range(-1, 2):
for offx in range(-1, 2):
if offx == 0 and offy == 0:
continue
for step in range(1, pads + 1):
if padded[pads+y+offy*step][pads+x+offx*step] == seat:
break
if padded[pads+y+offy*step][pads+x+offx*step] == occ:
sur[y][x] += 1
break
new = np.zeros(image.shape, dtype=int)
for (y, x), c in np.ndenumerate(image):
new[y][x] = (occ if sur[y][x] == 0 and c == seat else
(seat if sur[y][x] >= 5 and c == occ else
c))
return new
fn = sys.argv[1] if len(sys.argv) > 1 else 'input11'
with open(fn) as f:
lines = [l.strip() for l in f.readlines()]
arr = np.asarray([tpl(l) for l in lines], dtype=int)
#p(arr)
while True:
new = frob(arr)
#p(new)
if (new == arr).all():
pp(sum(sum(new == (np.ones(new.shape) * occ))))
break
arr = new
arr = np.asarray([tpl(l) for l in lines], dtype=int)
while True:
new = throb(arr)
#p(new)
if (new == arr).all():
pp(sum(sum(new == (np.ones(new.shape) * occ))))
break
arr = new