import numpy as np, itertools cp=(0,1,1,1,1,1); p=6 def rows_lean(nu,K): A=1<>np.arange(nu-1,-1,-1))&1).astype(np.uint8) T=nu*p e=np.zeros((A,T),dtype=np.uint8) for t in range(T): ph=t%p; e[:,t]=U[:,t//p] if ph==0 else (1 if ph==5 else 0) d=np.array([cp[t%p] for t in range(T)],dtype=np.uint8) prev=np.broadcast_to(d,(A,T)); cur=e; out=np.zeros((A,K),dtype=np.uint8); out[:,0]=cur[:,0] for k in range(1,K): nxt=cur[:,1:]^(cur[:,:-1]|prev[:,:cur.shape[1]-1]); prev,cur=cur,nxt; out[:,k]=cur[:,0] return out nu=19; K=6*nu-6 B=rows_lean(nu,K) res=[] for M in range(6,K-6): alive=np.ones(B.shape[0],bool); stall=0; longest=0; emptied=False for k in range(M,K): lantern=k+1; before=int(alive.sum()); alive&=(B[:,k]==0); after=int(alive.sum()) if after==0: emptied=True; break if (lantern-1)%6!=0: stall = stall+1 if after==before else 0; longest=max(longest,stall) res.append((M,longest,emptied)) for lo,hi in ((6,30),(31,55),(56,80),(81,K-7)): sel=[(l,e) for m,l,e in res if lo<=m<=hi] full=[l for l,e in sel if e]; part=[l for l,e in sel if not e] print(f" M in [{lo:3d},{hi:3d}]: fully eliminated runs: max stall {max(full) if full else '-'} (mean {np.mean(full) if full else 0:.2f}); runs NOT eliminated by lantern {K}: {len(part)} (stall so far up to {max(part) if part else '-'})")