import numpy as np, time def attack(r,phase,K=140): N=1<>j)&1 # right cells 1..r x1=np.zeros((N,T),dtype=np.uint8) for t in range(T): x1[:,t]=R[:,0] left=np.concatenate([np.full((N,1),c[t],dtype=np.uint8),R[:,:-1]],1) right=np.concatenate([R[:,1:],np.zeros((N,1),dtype=np.uint8)],1) R=left^(R|right) a_prev=np.broadcast_to(c[:T],(N,T)).copy() a=c[1:T+1][None,:]^(c[:T][None,:]|x1) # forced left neighbour, every night row=np.zeros((N,K),dtype=np.uint8); row[:,0]=a[:,0] for k in range(1,K): nxt=a[:,1:]^(a[:,:-1]|a_prev[:,:a.shape[1]-1]); a_prev,a=a,nxt; row[:,k]=a[:,0] return row t0=time.time() for phase in (0,1): for r in (4,8,12,14): row=attack(r,phase) K=row.shape[1] last=np.array([np.nonzero(rw)[0].max()+1 if rw.any() else 0 for rw in row]) # longest dark stretch in the forced left half between depth 20 and K def longest0(rw): best=cur=0 for v in rw[20:]: cur=cur+1 if v==0 else 0; best=max(best,cur) return best lz=np.array([longest0(rw) for rw in row]) lit_far=row[:,K-40:].sum(1) print(f"centre phase {phase}, right radius {r:2d} ({len(row)} right halves): last lit cell of forced left half at depth >= {last.min()} (of {K});" f" lit cells in the last 40 depths: min {lit_far.min()}; longest dark stretch beyond depth 20: max {lz.max()} [{time.time()-t0:.0f}s]",flush=True)