#!/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