import sys E = { (y,x) for y,l in enumerate(sys.stdin.read().splitlines()) for x,c in enumerate(l) if c == '#' } def can(y,x): can1 = (y-1,x-1) not in E can2 = (y-1,x) not in E can3 = (y-1,x+1) not in E can4 = (y,x+1) not in E can5 = (y+1,x+1) not in E can6 = (y+1,x) not in E can7 = (y+1,x-1) not in E can8 = (y,x-1) not in E return [can1,can2,can3,can4,can5,can6,can7,can8] def canN(y,x,can1,can2,can3,can4,can5,can6,can7,can8): if can1 and can2 and can3: return (y-1,x) def canS(y,x,can1,can2,can3,can4,can5,can6,can7,can8): if can5 and can6 and can7: return (y+1,x) def canW(y,x,can1,can2,can3,can4,can5,can6,can7,can8): if can7 and can8 and can1: return (y,x-1) def canE(y,x,can1,can2,can3,can4,can5,can6,can7,can8): if can3 and can4 and can5: return (y,x+1) def draw(r): with open(f"./pics/{r:05d}.pbm","wt") as f: (minx,maxx,miny,maxy) = (-13,129,-13,129) w = 4*(maxx -minx +1) print("P1",file=f) print(f"{w} {w}", file=f) for y in range(miny,maxy+1): a="".join(["0000","1111"][(y,x) in E] for x in range(minx,maxx+1)) print(a,file=f) print(a,file=f) print(a,file=f) print(a,file=f) from collections import deque dirs = deque([canN,canS,canW,canE]) for r in range(int(sys.argv[1])): # rounds P = dict() # { new_pos: old_pos } for e in E: # for each elve (y,x) = e cans = can(y,x) # compute once instead of four moves = [ d(y,x,*cans) for d in dirs ] if all(m is not None for m in moves): # far away continue if all(m is None for m in moves): # all packed continue p = next(filter(lambda m: m is not None ,moves)) if p not in P: # can move P[p] = (y,x) else: # occupied, invalidate move for all P[p] = None moved = { v for k,v in P.items() if v is not None } newpos = { k for k,v in P.items() if v is not None } if len(newpos) == 0: break if r % 11 == 0: draw(r) E = (E - moved) | newpos dirs.rotate(-1) # then, $TIME convert -delay 25 -loop 0 pics/* a.gif