-
-
Save DroneBetter/4f5d775e7c37f062ce750d4a8fefc84a to your computer and use it in GitHub Desktop.
Modification of gzip_swar_life.py supporting arbitrary isotropic non-totalistic cellular automata
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os,sys | |
from time import time,sleep | |
from functools import reduce | |
from dronery import dbg,redumulate,expumulate,shortduce,ORsum,maph,filterh,lap,tap,taph,saph,tarmap,tarmaph,charmap,factorise,primate,revange,loduct,tilter,permutation,decompose,recompose,id,rle,Fraction,__add__,__or__,compose,minh,maxh,reshape,denest,transpose,stratrix,bitverse,sap,rgetitem,sortduct | |
#print('\n'.join(map(lambda n: ''.join(map(lambda x: 'o' if x else ' ',(lambda x: map(lambda i: x>>3*i+1&1,range(x.bit_length()//3+1)))(n))),redumulate(lambda x,i: (lambda x: reduce(int.__or__,map(lambda j: (lambda x: x>>1&x&x<<1)(~x^i*j),(2,3,4,5,6))))(x>>4|x|x<<4)&i<<1,redumulate(lambda x,i: x|1<<3*i,range(2,64),9),2))));exit() | |
from itertools import product,starmap,accumulate,groupby,chain,islice,pairwise | |
try: | |
from itertools import batched | |
except: | |
def batched(l,n): | |
it=iter(l) | |
while batch:=tuple(islice(it,n)): yield(batch) | |
from math import isqrt,sqrt,gcd,lcm | |
digits={"0","1","2","3","4","5","6","7","8","9"} | |
""" | |
Modification of https://gist.github.com/DavidBuchanan314/acae2aab38953759aacc114b417ed0b9 supporting arbitrary OT and INT rules and topological manifolds | |
manifold=(x type, y type), type 0 is bounded, 1 is cylindrical, 2 is Möbius | |
States are stored as integers, moving along the bits will scroll in the x axis according to the width and increment the y value each time | |
The convention for outer-totalistic rules (such that each cell's state depends on its previous value and the sum of its neighbouring eight cells) is to store 4 bits per cell, with the last bit determining its value | |
It is added with copies of itself shifted leftwards and rightwards by 4 bits so each cell becomes the sum of its horizontal neighbours, then again by 4*WIDTH bits to sum with its vertical ones and their horizontal ones also | |
After this, for each sum that is a birth or survival condition the summed state is bitwise XORed with a constant that is the NOT of the desired sum for each cell, so those that become 1111 satisfy the sum | |
This is 'folded' by bitwise ANDing with itself shifted left by 2 bits, then again by 1, then with a constant that is 1 for each cell's last bit | |
Enact this for all outer totals (keeping in mind that survivals are 1 greater than in notation due to including themselves), bitwise OR those that are exclusively birth, exclusively survival and both, respectively, into three integers | |
Bitwise OR (the exclusively birth one AND NOT the original state), (the exclusively survival one AND the original state) and the both one together, to get the next state | |
For isotropic non-totalistic rules (similar to OT ones but depending on the configuration of the neighbours under symmetry as well as their sum), my initial idea was to store them as bits in the centres of their own 3*3 regions in the integer (instead of 4*1), so each can become a copy of its neighbourhood, and then XOR with the NOTs of the desired ones (and so forth) like originally | |
However, I realised each can instead be an 8*1 region in its outer neighbourhood excluding itself (now enabled by default in byteINT) | |
Here is one cell in the centre of its neighbourhood | |
| | | |
| o| | |
| | | |
First, we OR together itself shifted by (1,0), (0,1) and (-1,-1) | |
| o| | |
| |o | |
| o | | |
Then we OR this with (itself shifted by (3,0) AND a constant that is 01100000 for each bit) and itself shifted by (-11,0) | |
o | o| o | |
o | |o | |
o | o | o | |
The indexes of the state of the central cell within each neighbour are thus | |
3 | 0| 5 | |
2 | |7 | |
4 | 1 | 6 | |
The transitions are again ANDed with the original state or its NOT (depending on whether they're birth or survival) | |
This allows their encoding as videos without using gzip to convert cells of 4 bits to bytes | |
""" | |
manifold=(0,0) #0: edges, 1: cylinddrical, 2: Möbius | |
FPS=10 #Reduce if your media player is buffering. | |
totalTransitions=({"c"}, #using c for 0 and 8 because otherwise no distinction from empty set | |
{"c","e"}, | |
{"c","e","k","a","i","n"}, | |
{"c","e","k","a","i","n","y","q","j","r"}, | |
{"c","e","k","a","i","n","y","q","j","r","t","w","z"}, | |
{"c","e","k","a","i","n","y","q","j","r"}, | |
{"c","e","k","a","i","n"}, | |
{"c","e"}, | |
{"c"}) #if squares had more edges and vertices, it would approach a normal distribution, I think | |
transitionLetters=("c","e","k","a","i","n","y","q","j","r","t","w","z") | |
transitionTotals=tap(len,totalTransitions) | |
transitionIndexes=tuple(redumulate(int.__add__,transitionTotals[:-1],0)) #(could be islice(dronery.polynomial.infdiv(transitionTotals,(1,-1)),0,9) :-) | |
regularTransitions=tuple(charmap(lambda i,t: tap(str(i).__add__,transitionLetters[:t]),enumerate(transitionTotals))) | |
reducerTransitions=("0c","1c","2c","3c","2n","4c","1e","2a","2k","3n","3i","4n","3q","3y","4y","5e","2e","3a","3j","4a","4w","5a","3k","4q","4k","5j","5k","6e","3e","4r","4j","5n","5i","6a","5q","5y","6k","7e","2i","3r","4i","4t","5r","4z","6i","4e","5c","6c","7c","6n","8c") #from eightfold_reducer import reducer;reducer(3) will return them in this order | |
reducerPermutation=permutation(0x11c62736cec85cd1c29f0e06b5affb6285d47a8fbedbcbb077f39e)#permutation(tap(reducerTransitions.index,regularTransitions)) | |
transitions=tarmap(str.__add__,product(("B","S"),reducerTransitions)) | |
unreducedTransitions=(0,1,6,7,1,2,7,10,6,7,16,17,8,9,18,19,51,52,57,58,52,53,58,61,57,58,67,68,59,60,69,70,6,8,16,18,7,9,17,19,38,39,28,29,39,40,29,32,57,59,67,69,58,60,68,70,89,90,79,80,90,91,80,83,1,2,8,9,4,3,12,11,7,10,18,19,12,11,20,21,52,53,59,60,55,54,63,62,58,61,69,70,63,62,71,72,8,13,22,24,12,14,23,25,39,41,30,31,43,42,34,33,59,64,73,75,63,65,74,76,90,92,81,82,94,93,85,84,6,8,38,39,8,13,39,41,16,18,28,29,22,24,30,31,57,59,89,90,59,64,90,92,67,69,79,80,73,75,81,82,16,22,28,30,18,24,29,31,28,30,45,46,30,35,46,47,67,73,79,81,69,75,80,82,79,81,96,97,81,86,97,98,7,9,39,40,12,14,43,42,17,19,29,32,23,25,34,33,58,60,90,91,63,65,94,93,68,70,80,83,74,76,85,84,18,24,30,35,20,26,34,36,29,31,46,47,34,36,49,48,69,75,81,86,71,77,85,87,80,82,97,98,85,87,100,99,1,4,8,12,2,3,9,11,8,12,22,23,13,14,24,25,52,55,59,63,53,54,60,62,59,63,73,74,64,65,75,76,7,12,18,20,10,11,19,21,39,43,30,34,41,42,31,33,58,63,69,71,61,62,70,72,90,94,81,85,92,93,82,84,2,3,13,14,3,5,14,15,9,11,24,25,14,15,26,27,53,54,64,65,54,56,65,66,60,62,75,76,65,66,77,78,9,14,24,26,11,15,25,27,40,42,35,36,42,44,36,37,60,65,75,77,62,66,76,78,91,93,86,87,93,95,87,88,7,12,39,43,9,14,40,42,18,20,30,34,24,26,35,36,58,63,90,94,60,65,91,93,69,71,81,85,75,77,86,87,17,23,29,34,19,25,32,33,29,34,46,49,31,36,47,48,68,74,80,85,70,76,83,84,80,85,97,100,82,87,98,99,10,11,41,42,11,15,42,44,19,21,31,33,25,27,36,37,61,62,92,93,62,66,93,95,70,72,82,84,76,78,87,88,19,25,31,36,21,27,33,37,32,33,47,48,33,37,48,50,70,76,82,87,72,78,84,88,83,84,98,99,84,88,99,101) #indices in transitions list of each neighbourhood | |
reducedTransitions=tap(unreducedTransitions.index,range(102)) | |
def setRule(string): | |
global rulestring,OT,byteINT,ruleTotalTransitions,rule,transitionInt,totalSums,minuses,rulestring,RLErulestring,dualRule,b1c,b1e,b2c,b2a,b3i,edges,corners,nearCorners,gutterPreservation,cellWidth,cellHeight,cellBits | |
rulestring=string.lower().replace("/",'').replace("b",'').split("s") | |
byteINT=True | |
ruleTotalTransitions=[[set() for _ in range(9)] for _ in range(2)] | |
for i,r in enumerate(rulestring): | |
accumulator='' | |
for t in reversed(r): | |
if t in {"0","1","2","3","4","5","6","7","8"}: | |
ruleTotalTransitions[i][int(t)]=(totalTransitions[int(t)] if accumulator=='' else totalTransitions[int(t)]-set(accumulator) if "-" in accumulator else set(accumulator)) | |
accumulator='' | |
else: | |
accumulator+=t | |
rule={("S" if i else "B")+str(j)+t for i,s in enumerate(ruleTotalTransitions) for j,ss in enumerate(s) for t in ss} | |
#rule^=set(transitions) | |
pairs=(('c','e'),('i','t'),('n','r'),('y','j'),('q','w')) | |
#rule=set(map(lambda t: (lambda s,n,t: ('b' if s=='s' else 's')+str(8-int(n))+((lambda c: (lambda p: p[1^p.index(t)])(pairs[c.index(True)]) if any(c) else t)(lap(lambda p: p.__contains__(t),pairs)) if n=='4' else t))(*t),rule)) | |
totalSums=tuple(tuple(sum((("s" if i else "b")+str(j)+t in rule) for t in s) for j,s in enumerate(totalTransitions)) for i in range(2)) | |
minuses=tuple(tuple(--0--len(t)>>1<j<len(t) for j,t in zip(i,totalTransitions)) for i in totalSums) | |
(rulestring,RLErulestring)=(b+s.join(''.join(''.join(str(j)*(y!=0)+("-"*m+''.join(t for k,t in enumerate(u) if (("s" if i else "b")+str(j)+str(t) in rule)^m))*(y!=len(u))) for j,(y,u,m) in enumerate(zip(w,totalTransitions,x))) for i,(w,x) in enumerate(zip(totalSums,minuses))) for b,s in zip(("b","B"),("s","/S"))) | |
#print(rulestring);exit() #these three commented parts for inverting rule | |
OT=not(any(any((i in j) for j in rulestring) for i in totalTransitions[4])) | |
dualRule=[lap(rule.__contains__,transitions[51*i:51*(i+1)]) for i in range(2)] #the rule that is dual | |
rule=lap(rule.__contains__,transitions) | |
transitionInt=ORsum(starmap(lambda i,t: t<<i,enumerate(rule))) | |
checkTransition=(lambda transition: rule[transitions.index(transition)]) | |
if manifold[0]==0 or manifold[1]==0: | |
(b1c,b1e,b2c,b2a,b3i)=map(checkTransition,("B1c","B1e","B2c","B2a","B3i")) | |
edges=(b1c or b1e or b2c or b2a or b3i) | |
if not any(manifold): | |
corners=b1c | |
nearCorners=(b1e or b2a) #not b1c because that will be detected by edges and corners | |
else: | |
corners=False | |
nearCorners=edges | |
else: | |
corners=nearCorners=edges=False | |
gutterPreservation=(edges and not any(map(checkTransition,("B2c","B2i","B4c","B4i","B6i")))) | |
rule=lap(rule.__getitem__,unreducedTransitions) | |
cellWidth=(4 if OT else 8 if byteINT else 3) | |
cellHeight=(1 if OT or byteINT else 3) | |
cellBits=cellWidth*cellHeight | |
loadRule=setRule | |
dual=lambda f,r: ORsum(starmap(lambda i,t: t<<unreducedTransitions[f(reducedTransitions[i])],enumerate(decompose(r,102)))) | |
reversal=lambda r: dual((~(~0<<9)).__xor__,~r) | |
strobing=lambda r: (~(~0<<102)^r,dual((~(~0<<9)).__xor__,r)) | |
checker=lambda r: (dual((~(~0<<9)//3).__xor__,r),dual((~(~0<<10)//3).__xor__,~r)) | |
rulestringer=lambda transitionInt: (lambda transitionInt: 'B'+'/S'.join(map(lambda s: ''.join(starmap(lambda i,t: (lambda r: (lambda s: bool(u)*str(i)+(m and bool(s))*'-'+s)(''.join(sorted(starmap(lambda i,s: s*transitionLetters[i],enumerate(map((1).__xor__,r) if (m:=(u:=sum(r))>t[1]>>1) else r))))))(tap(lambda r: transitionInt>>51*s+r&1,range(t[0],t[0]+t[1]))),enumerate(zip(transitionIndexes,transitionTotals)))),range(2))))(recompose(reducerPermutation((t:=tuple(decompose(transitionInt,102)))[:51])+reducerPermutation(t[51:]))) | |
contains=lambda r,t: r>>reducerTransitions.index((t:=t+'c'*(len(t)==2))[1:])+51*(t[0].lower()=='s')&1 | |
def dualities(inputString): | |
global transitionInt | |
setRule(inputString) | |
if rulestringer(transitionInt)!=inputString: | |
print('your rule is '+rulestringer(transitionInt)) | |
ruleReversal=reversal(transitionInt) | |
if (selfInverse:=ruleReversal==transitionInt): | |
print('it is self-inverse') | |
else: | |
print('the reversal is '+rulestringer(ruleReversal)) | |
strule=strobing(transitionInt) | |
chule=checker(transitionInt) | |
print('the strobing dual is '+rulestringer(strule[0])+(not selfInverse)*(' and '+rulestringer(strule[1])+' alternating in time')) | |
print('the checkerboard dual is '+rulestringer(chule[0])+(not selfInverse)*(' and '+rulestringer(chule[1])+' alternating in space')) | |
#dualities(input('>>> '));exit() | |
'''count=0 | |
for b,s in product(range(1<<9),repeat=2): | |
setRule('b'+'s'.join(map(lambda t: ''.join(map(lambda i: (t>>i&1)*str(i),range(9))),(b,s)))) | |
if checker(transitionInt)==2*(transitionInt,): count+=1;print('b'+'s'.join(map(lambda t: ''.join(map(lambda i: (t>>i&1)*str(i),range(9))),(b,s)))) | |
if not(s or b&7): print(b>>3) | |
print('count',count) | |
exit()''' | |
#print(tuple(tuple(i for i in range(9) if OTtransitions[0][i]^o and OTtransitions[1][i-1]^a) for o in range(2) for a in range(1+(not o))));exit() | |
shift=(lambda n,b: n<<-b if b<0 else n>>b) | |
bits=lambda n,k: (1<<n*k)//~(~0<<k) #more correctly, ORsum(1<<k*i for i in range(n))=~(~<<n*k)//~(~0<<k) | |
def setBoard(w,h,manifoldModes=True): | |
global boardWidth,boardHeight,WIDTH,HEIGHT,STATE_BYTE_LENGTH,innerCOLSHIFT,COLSHIFT,WRAPSHIFT,BIAS,WRAP_MASK,lastColumn,firstColumn,MASK_1,emptyColumns | |
boardWidth=w;boardHeight=h | |
WIDTH=boardWidth+2;HEIGHT=boardHeight+2 | |
STATE_BYTE_LENGTH=(boardWidth*boardHeight>>OT if OT or byteINT else --0--9*boardWidth*boardHeight//8) | |
innerCOLSHIFT=cellWidth*boardWidth | |
COLSHIFT=cellBits*WIDTH | |
WRAPSHIFT=COLSHIFT*boardHeight | |
BIAS=((WIDTH+1)*cellWidth if OT or byteINT else (WIDTH*cellBits+1)*4) | |
unitNeighbourhood=0xf if OT else 0xff if byteINT else bits(3,3*WIDTH)*0b111 | |
WRAP_MASK=bits(WIDTH,cellWidth)*unitNeighbourhood<<COLSHIFT | |
lastColumn=bits(HEIGHT,COLSHIFT)*unitNeighbourhood | |
firstColumn=shift(lastColumn,(cellWidth if OT or byteINT else 3*(1-WIDTH))-((OT or byteINT) and COLSHIFT)) | |
BLIT_MASK_1=( int.from_bytes((WIDTH*HEIGHT>>OT)*(b"\x11" if OT else b"\x01"),"little") | |
if OT or byteINT else | |
bits(WIDTH,cellWidth)*bits(HEIGHT,cellWidth*cellHeight*WIDTH)<<(1+3*WIDTH)*(not(OT or byteINT))) | |
MASK_1=~(~0<<COLSHIFT*(HEIGHT-1)|firstColumn|lastColumn)&~0<<COLSHIFT&BLIT_MASK_1 | |
emptyColumns=bits(WIDTH,8)*bits(HEIGHT,COLSHIFT)*0b1100000 | |
global OTtransitions,INTtransitions,irr,andnts,ands | |
if OT: | |
OTtransitions=tuple(tuple((str(i) in s) for i in range(9)) for s in rulestring.replace("b",'').split("s")) | |
(irr,andnts,ands)=(tuple(MASK_1*(0xf^i) for i in range(10) if (i<9 and OTtransitions[0][i])^o and OTtransitions[1][i-1]^a) for o in range(2) for a in range(1+(not o))) #(tuple(MASK_1*(15^i) for i,(b,s) in enumerate(OTtransitions[0],OTtransitions[1][-1:]+OTtransitions[1][:7]) if b^o and s^a) for o in range(2) for a in range(1+(not o))) | |
elif byteINT: | |
(irr,andnts,ands)=(tuple({MASK_1*ORsum((~i>>j&1)<<(5,0,3,7,-1,2,6,1,4)[j] for j in tuple(range(4))+tuple(range(5,9))) for k,(b,s) in enumerate(zip(*dualRule)) if b^o and s^a for i,r in enumerate(unreducedTransitions) if r%51==k and (s if r//51 else b)}) for o in range(2) for a in range(1+(not o))) | |
else: | |
INTtransitions=tuple(MASK_1*ORsum((~i&1<<3*j)<<3*(WIDTH-1)*j for j in range(3))>>WIDTH*3+1 for i,r in enumerate(rule) if r) | |
if manifoldModes: | |
def reversalParameters(axis=0,inputWidth=WIDTH): #axis=0 for none, 1 for x, 2 for y | |
if axis: | |
inputWidth=(WIDTH if axis==2 else HEIGHT) | |
masks=[[[m,1<<i,False],[m,0,True]] for i,m in enumerate(andMasks(inputWidth))] #mask, shift right, order (True is shift after) | |
exceeding=(1<<(inputWidth-1).bit_length())-inputWidth | |
if exceeding: | |
endShifts=[-exceeding>>1,exceeding>>1] | |
#print(inputWidth,endShifts) | |
for i,m in enumerate(masks): | |
#print(m[0][1]) | |
shifter=(lambda i,m: min(m[0][1],m[0][1]-(2<<i),key=abs)) | |
if -endShifts[0]<=shifter(i,m): | |
m[0][1]+=endShifts[0] | |
m[1][0]>>=-endShifts[0] | |
break | |
else: | |
m[0][0]>>=m[0][1]-endShifts[0] | |
m[0][1]-=endShifts[0] | |
m[0][2]=True | |
m[1][0]>>=-endShifts[0] | |
common=(m[0][1]^m[0][1]-(2<<i)>0 and shifter(i,m)) | |
if common: | |
endShifts[0]=-common | |
if endShifts[0]<m[0][1]: | |
m[0][1]=0 | |
else: | |
break | |
masks[-1][0][0]>>=endShifts[1] | |
masks[-1][0][1]+=endShifts[1] | |
'''for i,m in enumerate(masks): | |
for a in m: | |
if not i: #or a[1]>0 | |
a[0]&=(1<<(inputWidth-a[1] if a[1]<0 and not a[2] else inputWidth))-1''' #small optimisation but turns out not to work for all values not three quarters of a power of 2 | |
for i,m in enumerate(masks): | |
m[1][1]=m[0][1]-2*(1<<i) | |
bytewise=(lambda m: [ORsum((m[0]&1<<i)<<(cellWidth-1)*i for i in range(1<<(inputWidth-1).bit_length()))<<(not(OT or byteINT) and 3*WIDTH+1),cellWidth*m[1],m[2]]) | |
if axis: | |
masks=[[( [(l:=ORsum((n&1<<(cellWidth*i if OT or byteINT else 3*(WIDTH+i)+1))<<cellWidth*(cellHeight*WIDTH-1)*i for i in range(1<<(HEIGHT-1).bit_length())))|l<<cellWidth*(WIDTH-1),s*cellHeight*WIDTH,o] | |
if axis==1 else | |
[n|n<<COLSHIFT*(HEIGHT-1),s,o]) for n,s,o in map(bytewise,m)] for m in masks] | |
#print("\n".join(hex(n[0]) for m in masks for n in m)) | |
'''if axis: | |
for m in masks: | |
for i,n in enumerate(m): | |
printBoard(n[0],False,("+" if i else "-"))''' | |
conditionalSwap=(lambda x,b,t,f,br: '('*br+x+(t+')'*br+f if b else f+')'*br+t)) | |
indent=(lambda i,t: " "*(i>len(t) and i-len(t))+t) | |
marge=[max(len(str((abs if i else hex)(n[i]))) for m in masks for n in m) for i in range(2)] | |
return("def reverseBits"+("Y" if axis==2 else "X" if axis else '')+"(x):\n "+"\n ".join("x="+'|'.join(conditionalSwap('x',(n[2] and n[1]),"&"+indent(marge[0],str(hex(n[0]))),((">>" if n[1]>0 else "<<")+indent(marge[1],str(abs(n[1]))) if n[1] else ' '*(2+marge[1])),(n[1] and n[2])) for n in m) for m in masks)+"\n return(x)") | |
global reverseBits,reverseBitsX,reverseBitsY | |
for i in range(3): | |
#print(reversalParameters(i)) | |
exec(reversalParameters(i)) | |
niemiec=True #whimsical | |
boardRow=lambda board,i: board>>(cellWidth*WIDTH*i if OT or byteINT else 3*WIDTH*(i*3+1)+1)&~(~0<<cellWidth*WIDTH) | |
boardStr=(lambda board,inner=True,b='b',o='o',j='\n': j.join((lambda i: ''.join(o if i>>cellWidth*j&1 else b for j in range(inner,i.bit_length()//cellWidth+2-inner)))(boardRow(board,i)) for i in range(inner,HEIGHT-inner))) | |
phaseStr=(lambda boards,inner=True,o='o',_='_',O='O',j='\n': j.join((lambda i: ''.join((lambda i: (((o,_,O)[i-1] if False else (O if i==(1<<len(boards))-1 else o) if i&1 else _)) if i else ' '*len(o))(ORsum(starmap(lambda i,s: (s>>cellWidth*j&1)<<i,enumerate(i)))) for j in range(inner,WIDTH-inner)))(tap(lambda b: boardRow(b,i),boards)) for i in range(inner,HEIGHT-inner))) | |
blocks=(lambda board,inner=True: '\n'.join(map(lambda p: ''.join(map(lambda a,b: ' ▄▀█'[a<<1|b],*(p if len(p)==2 else p+((0,)*len(p),)))),batched(map(lambda i: (lambda i: map(lambda j: i>>cellWidth*j&1,range(inner,WIDTH-inner)))(boardRow(board,i)),range(inner,HEIGHT+1-inner)),2)))) | |
def printBoard(board,inner=True,symbol="=",phases=False,end='\n'): | |
print(symbol*(boardWidth if inner else WIDTH)+"\n"+(phaseStr(board,inner,*(('▓▓','░░'),('▒▒','░░'))[0],'██') if phases else blocks(board,inner)),end=end) #boardStr(board,inner,' ','o','\n')) | |
RLE=(lambda board,inner=True,includeRule=False: ("x ="+str(boardWidth)+", y = "+str(boardHeight)+", rule = "+RLErulestring+"\n")*includeRule+''.join((lambda l,q: l*2 if niemiec and q==2 else l if q==1 else str(q)+l)(l,len(list(q))) for l,q in groupby(boardStr(board,inner,'b','o','$')))+"!") | |
cellsAtCoordinates=(lambda cells: ORsum(1<<cellWidth*(x+cellHeight*y*WIDTH) for x,y in cells)<<BIAS) | |
def proceed(RLE,i): | |
while RLE[i] in set("x y, =rule"): | |
i+=1 | |
return(i) | |
def RLEsize(RLE): #for headerless ones | |
width=height=0 | |
arm=0 | |
output=0 | |
endOfTheLine=False #"end of the line" | |
stringer='' #like finger | |
for r in RLE.replace(' ',''): | |
if r in digits: | |
stringer+=r | |
else: | |
stringer=(int(stringer) if stringer else 1) | |
if r=="$": | |
height+=stringer | |
arm=0 | |
endOfTheLine=False | |
else: | |
if r=="!": | |
break | |
if r and r!='\n': | |
arm+=stringer | |
if arm>width: width=arm | |
stringer='' | |
return((width,height+1)) | |
def loadRLE(RLE): | |
if RLE[0]=='x': | |
i=1 | |
size=[] | |
for di in range(2): | |
stringer='' | |
i=proceed(RLE,i) | |
for i,r in enumerate(RLE[i:],start=i): | |
if r in digits: | |
stringer+=r | |
else: | |
break | |
size.append(int(stringer)) | |
global boardWidth,boardHeight,WIDTH,HEIGHT,STATE_BYTE_LENGTH,innerCOLSHIFT,COLSHIFT,WRAPSHIFT,BIAS,WRAP_MASK,lastColumn,firstColumn,MASK_1,emptyColumns #please tell me if you can find a better way than this of having inner functions set globals | |
setBoard(*size) | |
i=proceed(RLE,i) | |
global rulestring,OT,byteINT,ruleTotalTransitions,rule,totalSums,minuses,rulestring,RLErulestring,dualRule,b1c,b1e,b2c,b2a,b3i,edges,corners,nearCorners,gutterPreservation,cellWidth,cellHeight,cellBits | |
setRule(RLE[i:(i:=RLE.index('\n'))]) #distinct from \n | |
else: | |
i=0 | |
arm=0 | |
output=0 | |
endOfTheLine=False #"end of the line" | |
stringer='' #like finger | |
#print(RLE[i:]) | |
for r in RLE[i:].replace(' ',''): | |
if r in digits: | |
stringer+=r | |
else: | |
stringer=(int(stringer) if stringer else 1) | |
if r=="$": | |
arm=(arm//boardWidth-endOfTheLine+stringer)*boardWidth | |
#arm+=(stringer-endOfTheLine)*boardWidth-arm%boardWidth #hmm (not sure which I like more) | |
endOfTheLine=False | |
else: | |
if r=="o": | |
output|=ORsum(1<<s%boardWidth*cellWidth for s in range(arm,arm+stringer))<<arm//boardWidth*COLSHIFT+BIAS | |
elif r=="!": | |
break | |
if r and r!='\n': | |
arm+=stringer | |
endOfTheLine=not(arm%boardWidth) | |
stringer='' | |
return(output) | |
#andMasks=(lambda inputWidth: tap(lambda i: reduce(lambda n,j: n|n<<(1<<j),range(i+1,bitWidth),(1<<(1<<i))-1),range(bitWidth:=(inputWidth-1).bit_length()))) #equivalently, | |
andMasks=(lambda inputWidth: tap(lambda i: ~(~0<<(1<<bitWidth))//(1<<(1<<i)|1),range(bitWidth:=(inputWidth-1).bit_length()))) #thank you Donald Knuth (https://www-cs-faculty.stanford.edu/~knuth/fasc1a.ps.gz :-) | |
colmask=lambda x: lastColumn<<cellWidth*(x+1) | |
rowmask=lambda y: WRAP_MASK<<COLSHIFT*y | |
def marginalise(state,marginalisation=1): #very suspicious (marginalisation 2 causes it to only grow, 1 causes it to recede also, 0 doesn't call it) | |
if state: | |
global boardWidth,boardHeight,WIDTH,HEIGHT,STATE_BYTE_LENGTH,innerCOLSHIFT,COLSHIFT,WRAPSHIFT,BIAS,WRAP_MASK,lastColumn,firstColumn,MASK_1,emptyColumns,OTtransitions,INTtransitions,irr,andnts,ands | |
for minX in range(boardWidth): | |
if colmask(minX)&state: | |
break | |
for maxX in revange(boardWidth): | |
if colmask(maxX)&state: | |
break | |
for minY in range(boardHeight): | |
if rowmask(minY)&state: | |
break | |
for maxY in revange(boardHeight): | |
if rowmask(maxY)&state: | |
break | |
state=RLE(state) | |
if marginalisation==2: | |
minX=min(minX,1);maxX=max(maxX,boardWidth+~1);minY=min(minY,1);maxY=max(maxY,boardHeight+~1) | |
setBoard(maxX+4+~minX,maxY+4+~minY,False) #no manifolds when marginalising | |
global shiftX,shiftY | |
shiftX=minX-1;shiftY=minY-1 | |
return(shift(loadRLE(state),shiftX*cellWidth+shiftY*COLSHIFT)) | |
else: | |
raise(ValueError("empty :-(")) | |
yuv4mpeg=False#(OT and input("Would you like YUV4MPEG mode?").lower() in {"y","yes"}) | |
deflate_verbatim=(lambda data: len(data).to_bytes(2,"little")+(len(data)^0xffff).to_bytes(2,"little")+data) | |
if yuv4mpeg: | |
GZIP_HEADER = b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03" | |
YUV_HEADER = f"YUV4MPEG2 W{WIDTH} H{HEIGHT} F{FPS}:1 Cmono\n".encode() | |
#This tree could be encoded more concisely, but I'm lazy | |
MAGIC_HUFFMAN_TREE = bytes.fromhex(f"6ce30990244992244908fc{'f'*60}00000020{'2'*14}0000") | |
sys.stdout.buffer.write(GZIP_HEADER) | |
sys.stdout.buffer.write(b"\x00" + deflate_verbatim(YUV_HEADER) + b"\x00") | |
def loadapg(apgcode,p=False): | |
if apgcode[:2] in {"xp","xq"}: #could be "xs" except still lifes are not very interesting to analyse | |
global objectType | |
objectType=('p','q').index(apgcode[1]) | |
period='' | |
i=2 | |
while apgcode[i] in digits: | |
period+=apgcode[i] | |
i+=1 | |
period=int(period) | |
inelegant=[[] for _ in range(5)] #cannot be [[]]*5 because then they are the same | |
z=0 | |
sleepy=False | |
for i in apgcode[i+1:]: | |
if sleepy: | |
n="0123456789abcdefghijklmnopqrstuvwxyz".index(i)+4 | |
for j in range(5): | |
inelegant[5*z+j]+=[0]*n | |
sleepy=False | |
else: | |
if i=='z': | |
inelegant+=[[] for _ in range(5)] | |
z+=1 | |
else: | |
try: | |
cells="0123456789abcdefghijklmnopqrstuv".index(i) | |
for j in range(5): | |
inelegant[5*z+j].append(cells>>j&1) | |
except: | |
if i=='y': | |
sleepy=True | |
else: | |
for j in range(5): | |
inelegant[5*z+j]+=[0]*(2+(i=='x')) | |
'''print('\n'.join(map(lambda l: ''.join(map(lambda c: 'o' if c else ' ',l)),inelegant))) | |
print(inelegant)''' | |
global boardWidth,boardHeight,WIDTH,HEIGHT,STATE_BYTE_LENGTH,innerCOLSHIFT,COLSHIFT,WRAPSHIFT,BIAS,WRAP_MASK,lastColumn,firstColumn,MASK_1,emptyColumns,OTtransitions,INTtransitions,irr,andnts,ands | |
setBoard(max((i for j in inelegant for i,k in enumerate(j) if k),default=0)+1,max(i for i,j in enumerate(inelegant) if any(j))+1) | |
if p: | |
global state | |
state=loadRLE('$'.join(map(lambda l: ''.join(map(lambda c: 'o' if c else 'b',l)),inelegant))+'!') | |
return(period if p else state) | |
else: | |
raise(ValueError('not xp or xq')) | |
'''critterMask=1 | |
(stro,crit,ters)=tap(lambda n: eval('lambda state: '+('|'.join(map(lambda i: (lambda s: (lambda d: '('+d[:(f:=d.find('s'))]+('(s:='+s+')' if d.count('s')>1 else '('+s+')')+d[f+1:]+')' if 's' in d else d or '0')((lambda n: '|'.join(filter(id,map(lambda i: (n>>i&1)*('s'+bool(i)*('<<'+str((i&1)+COLSHIFT*(i>>1&1)))),range(4)))))(n>>(i<<2))))((~i&1)*'~'+'state&'+(~i>>1&1)*'~'+'state>>1&'+(~i>>2&1)*'~'+'state>>'+str(COLSHIFT)+'&'+(~i>>3&1)*'~'+'state>>'+str(COLSHIFT+1)+'&'+str(critterMask)),range(1<<4))) or '0')), #extremely unoptimised | |
(0xfed3b56179a2c480, #(0b1111_1110_1101_0011_1011_0101_0110_0001_0111_1001_1010_0010_1100_0100_1000_0000, | |
0x08432a97165bcdef, # 0b0000_1000_0100_0011_0010_1010_1001_0111_0001_0110_0101_1011_1100_1101_1110_1111, | |
0x01234a9e865dcb7f))# 0b0000_0001_0010_0011_0100_1010_1001_1110_1000_0110_0101_1101_1100_1011_0111_1111)) | |
#exit()''' | |
def iterateCellular(state,marginalisation=0): | |
global WIDTH,HEIGHT,innerCOLSHIFT,COLSHIFT,WRAPSHIFT,WRAP_MASK,lastColumn,firstColumn,MASK_1,emptyColumns,INTtransitions,irr,andnts,ands | |
if marginalisation: | |
global shiftX,shiftY | |
state=marginalise(state,marginalisation) | |
if manifold[0]: | |
state|=(reverseBitsX if manifold[0]==2 else id)(state>>innerCOLSHIFT&lastColumn|state<<innerCOLSHIFT&firstColumn) | |
if manifold[1]: | |
state|=(reverseBitsY if manifold[1]==2 else id)(state>>WRAPSHIFT|(state&WRAP_MASK)<<WRAPSHIFT) | |
if OT or byteINT: | |
summed=( ((s:=(state>>4)+state+(state<<4))>>COLSHIFT)+s+(s<<COLSHIFT) | |
if OT else | |
(s:=state>>1|state>>COLSHIFT|state<<COLSHIFT+1)<<11|s|s>>3&emptyColumns) | |
masks=[ORsum(((s:=(s:=summed^r)&s>>1)&s>>2 if OT else (s:=(s:=(s:=summed^r)&s>>1)&s>>2)&s>>4) for r in o) for o in (irr,andnts,ands)] | |
return((state&masks[2]|masks[0]|masks[1]&~state)&MASK_1) | |
else: | |
return(ORsum((s:=(s:=((s:=state>>2|state|state<<2)>>6*WIDTH|s|s<<6*WIDTH)^r)>>1&s&s<<1)>>3*WIDTH&s&s<<3*WIDTH for r in INTtransitions)&MASK_1) | |
def analyse(apgcode,metric=(0,),interface=False,stateInstead=False): #0: volatility, 1: heat, 2: polyomino?, 3: minimum population, 4: gutter, -1: correct margins only | |
def polyomino(state): | |
omino=0 | |
newmino=1<<(state.bit_length()-1) | |
while newmino!=omino: | |
omino=newmino | |
newmino=(omino|(omino<<COLSHIFT+cellWidth|omino<<COLSHIFT-cellWidth|omino>>COLSHIFT-cellWidth|omino>>COLSHIFT+cellWidth if polyferz else omino<<COLSHIFT|omino<<cellWidth|omino>>cellWidth|omino>>COLSHIFT))&state | |
return(omino==state) | |
global state,objectType,period | |
period=loadapg(apgcode,True) | |
global boardWidth,boardHeight,WIDTH,HEIGHT,STATE_BYTE_LENGTH,innerCOLSHIFT,COLSHIFT,WRAPSHIFT,BIAS,WRAP_MASK,lastColumn,firstColumn,MASK_1,emptyColumns,OTtransitions,INTtransitions,irr,andnts,ands,shifts | |
originalSize=(boardWidth,boardHeight) | |
shifts=((1,1) if objectType else (0,0)) #would be (0,0) except it is very suspicious | |
global shiftX,shiftY | |
for i in range(period+1): | |
#printBoard(state) | |
state=iterateCellular(state,2-objectType) | |
if objectType: | |
shifts=tap(int.__add__,shifts,(shiftX,shiftY)) | |
if metric==-1: | |
if objectType: | |
state=RLE(state) | |
setBoard(boardWidth+abs(shifts[0]),boardHeight+abs(shifts[1])) | |
state=shift(loadRLE(state),(lambda f: -f(-shifts[0])*cellWidth-f(-shifts[1])*COLSHIFT)(lambda x: x>0 and x)) | |
return(period,state) | |
memory=state | |
accumulator=0 | |
energies=[] | |
differences=0 | |
minpop=state.bit_count() | |
poly=0 | |
measureStricts=True | |
if measureStricts: | |
factors=(lambda p: (1,)+factorise(p))(period)[:-1] #numbers are not proper divisors of themselves, however 1 detects stators :-) | |
#fates=[state for _ in factors] #factorStates :-) #this will not work (must sample full period, not only representatives) | |
unabidings=[0 for _ in factors] | |
pasts=[] #instead of fates | |
for i in range(period): | |
if measureStricts: pasts.append(state) #storing at indexes of primitive roots of unity would take list A000010(n)=O((1-6/pi**2)*n) elements long | |
#printBoard(state) | |
#if i: #(would enclose for loop) | |
for j,f in enumerate(factors): | |
if i>=f: | |
unabidings[j]|=state^pasts[i-f] | |
'''if not i%f: | |
unabidings[j]|=state^fates[j] #reduced OR of XORs of all from first to last contains XOR of last with first :-)''' | |
previous=state | |
accumulator|=state | |
state=iterateCellular(state,0) | |
if 3 in metric: | |
minpop=min(minpop,state.bit_count()) | |
if 2 in metric: | |
poly+=polyomino(state) | |
if 0 in metric or 1 in metric or 4 in metric: | |
difference=state^previous | |
differences|=difference | |
if 1 in metric: | |
energies.append(difference.bit_count()) | |
if 2 in metric: | |
if poly: printBoard(state) | |
if 1 in metric: | |
heat=sum(energies)/period | |
if 0 in metric: | |
rotor=differences.bit_count() | |
strictor=reduce(int.__and__,unabidings).bit_count() #only well-defined here for oscillators (spaceships in the mode with subpixels) #"strictor, come down for dinner" "not now, mother" | |
footprint=accumulator.bit_count() | |
volatility=rotor/footprint | |
strict=strictor/footprint | |
global gutter | |
if 4 in metric: | |
gutter=False | |
columns=tap(lambda x: (colmask(x)&accumulator).bit_count(),range(boardWidth)) | |
rows=tap(lambda y: (rowmask(y)&accumulator).bit_count(),range(boardHeight)) | |
for mask,d in ((colmask,columns),(rowmask,rows)): | |
mini=maxi=-1 | |
for x,c in enumerate(d): | |
if c: | |
if mini==-1: mini=x | |
maxi=x | |
for x,c in enumerate(d[mini+1:maxi],start=mini+1): | |
if not c and (mask(x-1)&differences or mask(x+1)&differences): gutter=True | |
if interface and (4 not in metric or gutter): | |
print('h',heat,'f',footprint,'r',rotor,'v',volatility,'s',strict) | |
return(gutter if 4 in metric else minpop if 3 in metric else poly if 2 in metric else heat if 1 in metric else (volatility,strict)) | |
if __name__=='__main__': | |
polyferz=False #unfortunately they do not exist | |
#dualities(input('rule '));exit() #for getting a rule's duals | |
mode=5 #0,1,2,3 (simulate RLE, sort census, exhaustively search bounded plane, make picture (or OT map) :-) | |
OTmap=0 #also for printing known spaceships in a given rule | |
setRule('b3s23' if mode==3 and OTmap or mode>3 else input("Which rule would you like? ") or 'b3s23') | |
setBoard(8,8) | |
#logarithmic replicator rule emulator rulestring | |
#setRule('B2a3eny4at/S01c2ci3i4e5e');setBoard(3,3);print(hex(ORsum(starmap(lambda i,p: ('','bo','obo','3o').index(RLE(iterateCellular(loadRLE('$'.join(map(('bbb','bob','obo','ooo').__getitem__,p))))).split('$')[1])<<2*i,enumerate(product(range(4),repeat=3))))));exit() | |
if mode==5: #2x2's | |
#transitions: (0,1,2e,2c,3,4) | |
ruleTransitionSet=set() | |
ruleTable=[] | |
l=[] | |
f=lambda r: lambda s: r>>2+((s^s>>1)&(s^s>>2)&1)&1 if (wt:=s.bit_count())==2 else r>>wt+(wt>2)&1 | |
rulestringer2x2=lambda r,space=0: ''.join(map(lambda i: ((' ','0'),(' ','1'),(' ','2e'),(' ','2c'),(' ','3'),(' ','4'))[i][r>>i&1],range(6)) if space else map(('0','1','2e','2c','3','4').__getitem__,filter(lambda i: r>>i&1,range(6)))).replace('2e2c','2'+' '*space).replace('e ','e').replace(' 2c','2c').replace(' ',' ') | |
reversal=lambda r: ~(r<<5|(r&0b10)<<3|r&0b1100|r>>3&0b10|r>>5&1)&0b111111 | |
convert2to3=lambda r0,r1: recompose(tap(lambda t: f(r1)(recompose(tap(lambda t: f(r0)(recompose(t)),reshape(denest(tap(compose(transpose,tuple),reshape(denest(tuple(pairwise(map(compose(pairwise,tuple),reshape(decompose(t,9),(3,3)))))),(2,2,2,2)))),(4,4))))),reducedTransitions)) | |
for r in chain.from_iterable(sorted(sap(lambda r: tuple(sorted((r,reversal(r)))),range(1,~(~0<<6)) if (excludeSelfForcers:=False) else range(1<<6)),key=lambda r: r[0])):#chain.from_iterable(map(lambda r: (r:=bitverse(r,5),~(~0<<6)^r),range(1<<5))):#range(1<<6): | |
rulestring=rulestringer2x2(r) | |
transitions2x2=convert2to3(r,r) | |
ruleTransitionSet.add(transitions2x2) | |
ruleTable.append([r,rulestringer2x2(r,1)]+rulestringer(transitions2x2).split('/')) #recompose(map(f,range(1<<4))) | |
l.append(transitions2x2) | |
#print(stratrix(tarmap(lambda i,r: tarmap(lambda j,u: int(rulestringer(r^u)==rulestringer(l[i^j])),enumerate(l)),enumerate(l)))) | |
#print(stratrix(((0,)+tuple(range(len(l))),)+tarmap(lambda i,r: (i,)+tarmap(lambda j,u: int(rulestringer(r^u)==rulestringer(l[i^j])),enumerate(l)),enumerate(l)))) | |
#print(tap(taph(rulestringer2x2),((0,63),(4,59),(8,55),(12,51),(18,45),(22,41),(26,37),(30,33)))) | |
#print(stratrix(tap(lambda r: tuple(decompose(r,6)),(chain.from_iterable(((0,63),(4,59),(8,55),(12,51),(18,45),(22,41),(26,37),(30,33))))))) | |
#print(stratrix(ruleTable,dims=2)) | |
def equivalences(l,f=lambda i,j: not(i^j),relation=0,sym='='): | |
equiv=[] | |
for i,j in product(range(102),repeat=2): | |
if i!=j and all(map(lambda r: f(r>>i&1,r>>j&1),l)): equiv.append([i,j]) | |
if relation: | |
i=0 | |
while i<len(equiv): | |
for j in range(i): | |
for k in range(2): | |
if equiv[i][k] in equiv[j]: | |
if equiv[i][~k&1] not in equiv[j]: | |
equiv[j].append(equiv[i][~k&1]) | |
del equiv[i];i=-1 | |
if i==-1: break | |
if i==-1: break | |
i+=1 | |
print(equiv) | |
print('\n'.join(map(compose(maph(transitions.__getitem__),(' '+sym+' ').join),equiv))) | |
maxlen=max(map(compose(rgetitem(2),len),ruleTable)) | |
#print('\n|-\n'.join(starmap(lambda i,r: '|'+'rowspan=2|r||'*(~i&1)+' '*(len(str(r[0]))==1)+str(r[0])+'||'+r[1].replace(' ',' ')+'||'+' '*(maxlen-len(r[2]))+r[2]+'/'+r[3],enumerate(ruleTable)))) | |
#print(len(set(l))) | |
#equivalences(l,lambda i,j: not i or j,sym='=>') | |
#equivalences(l,lambda i,j: i^j,sym='^') #does not even work with excludeSelfForcers | |
#c=tap(lambda r0: tap(lambda r1: convert2to3(r0,r1),range(1<<6)),range(1<<6)) #very inefficient but only needed to run once | |
from compositions_2to3 import c | |
convert2to3=lambda r0,r1: c[r0][r1] | |
l=tuple(chain.from_iterable(c)) | |
#print(l) | |
#equivalences(l) | |
#print(tap(taph(rulestringer),l)) | |
#print(tap(l.count,sorted(s:=set(l))),len(s)) | |
normalise=lambda r0,r1: (~(~0<<6)^r0,~(~0<<6)^reversal(r1)) if r0&1 else (r0,r1) | |
#binsort=lambda r: tuple(chain.from_iterable(sorted(map(sorted,reshape(r,(2,2)))))) #=lambda r: min(map(lambda n: tuple(chain.from_iterable(tap(lambda t: t[::(-1)**(n>>1)],reshape(r,(2,2)))[::(-1)**(n&1)])),range(4))) | |
equivalenceClass=lambda r0,r1: tarmap(normalise,((r0,r1),(r1,r0),(reversal(r0),reversal(r1)),(reversal(r1),reversal(r0)))) | |
s=sorted(set(starmap(lambda r0,r1: equivalenceClass(*min(equivalenceClass(r0,r1))),product(map((2).__mul__,range(1,1<<5)),range(1,~(~0<<6)))))) | |
maxlen=max(map(compose(lambda r: c[r[0]][r[1]],rulestringer,lambda s: s.index('/')),chain.from_iterable(s))) | |
table=lambda s: '\n|-\n'.join(map(lambda t: (lambda r: '|rowspan=3|r|| ||rowspan=2|c||'+r[0]+'\n|-\n|rowspan=3|r||'+r[1]+'\n|-\n|rowspan=2|c||'+r[2]+'\n|-\n| ||'+r[3])(tarmap(lambda r0,r1: (rulestringer2x2(r0,1)+'||'+rulestringer2x2(r1,1)).replace(' ',' ')+'||'+(maxlen-(s:=rulestringer(c[r0][r1])).index('/'))*' '+s,t)),s)) | |
#print(table(filter(lambda r: any(map(lambda r: not contains(convert2to3(*r),'B0'),r)),s))) | |
print(table(filter(lambda r: all(map(lambda r: contains(convert2to3(*r),'B0') and not contains(convert2to3(*r),'S8'),r)),s))) | |
print(len(s)) | |
strobing=lambda r: contains(r:=convert2to3(*r),'B0') and not contains(r,'S8') | |
print(len(tuple(filter(lambda r: any(map(lambda r: not contains(r:=convert2to3(*r),'B0'),r)),s)))) | |
print(len(tuple(filter(lambda r: not all(map(strobing,r)) and all(map(lambda r: contains(r:=convert2to3(*r),'B0') or not contains(r,'B1c') and any(map(lambda c: contains(r,c),('B1e','B2a','B2c','B3i'))) and any(map(lambda c: contains(r,c),('B1e','B2a','B2e','B3a'))),r)),s)))) | |
print(stratrix(tap(taph(rulestringer),undisproven:=tap(compose(filterh(lambda r: not contains(r:=convert2to3(*r),'B0')),tarmaph(convert2to3)),filter(lambda r: not all(map(strobing,r)) and all(map(lambda r: contains(r:=convert2to3(*r),'B0') or not contains(r,'B1c') and any(map(lambda c: contains(r,c),('B1e','B2a','B2c','B3i'))) and any(map(lambda c: contains(r,c),('B1e','B2a','B2e','B3a'))) and not all(map(lambda c: contains(r,c),('S0','S1c','S1e','S2c','S2e','S2k','S2a','S3a','S3i','S3n','S3j','S4a'))) and not all(map(lambda c: contains(r,c),('B1e','B2a'))),r)),s))),dims=2)) | |
print(tap(compose(lambda n: 'BS'[n//51]+reducerTransitions[n%51]),reduce(set.__and__,chain.from_iterable(tap(compose(filterh(lambda r: not contains(r,'B1e')),taph(lambda r: set(filter((r:=tuple(decompose(~(~0<<102)^r))).__getitem__,range(len(r)))))),undisproven))))) | |
print(len(undisproven)) | |
print(len(tuple(filter(lambda r: all(map(strobing,r)),s)))) | |
elif mode==4: #reformat | |
with open(os.path.join(sys.path[0],'c2-P098.json'),newline='') as db: #https://conwaylife.com/forums/viewtopic.php?p=171031#p171152 | |
for i,s in enumerate(db): | |
print('\n'.join(s.replace('.',' ').split('| --- |'))) | |
if i>20: break | |
elif mode==3: | |
from PIL import Image | |
rms=lambda c: sqrt(sum(tap((2.).__rpow__,c))/len(c)) #root-mean-square, not Richard Martin Stallman | |
triangleWave=lambda o,period=1: (lambda p: tap(rms(p).__rtruediv__,p))(tap(lambda c: (lambda o: 3*o if o<1/3 else o<2/3 and 2-3*o)((o/period+c/3)%1),range(3))) | |
if OTmap: | |
speed=(3,1,1) #speed given as (p,x,y) (with x>=y), or False/0 for all speeds | |
if speed[2]>speed[1]: speed=(speed[0],)+speed[2:0:-1] | |
rule=input('rule? (blank for map) ') | |
speedRequirement=bool(speed and not rule) #if on, spaceships of desired speed blue, otherwise they are green and others are hidden | |
printRLEs=rule!='' or speedRequirement and 0 #overrides the OT map; 1: particular rule, 2: self-complementary | |
particular=ORsum(starmap(lambda i,s: ORsum(map(lambda t: (str(t) in s)<<t,range(9)))<<9*i,enumerate(rule.lower().split('s')))) | |
particularSpeeds=set() | |
count=0 | |
prule=lambda r,sur=True: 'B'+'/S'.join(map(lambda n: ''.join(map(lambda i: str(i)*(n>>i&1),range(9))),(r&~(~0<<9),r>>9)[:1+sur])) | |
speedStr=lambda p,x,y: ('('+str(x)+','+str(y)+')' if y else (x!=1)*str(x))+'c/'+str(p) | |
mask=~(~0<<9) | |
'''spaceships=(0b111101101_111001000_000001100_000001000, #xq4_153 glider | |
0b110001100_101011000_000001100_000001000, #xq4_6frc LWSS | |
0b110011001_110001000_000011000_000001000, #xq3_2di2472z131 | |
0b111111001_111110100_000000000_000000100, #xq1_69 moon | |
0b111111100_111110100_000000000_000000100, #xq1_609 split moon | |
0b111000100_110000100_000000100_000001000, #xq3_c86302ia4g27g648gxg846g72g4ai20368czxc2104ey2chm0mhcy2e4012czy417qqi0ei8h4h8ie0iqq71 | |
0b000000110_111001000_000000110_000001000, #xq8_y1842ve4z8sqp821zw1 | |
0b111100000_111101000_111100000_111101000, #xq16_sususvsususzfvvvvvvvvvfzw3171713 | |
0b110100010_111110100_000100000_000110100, #xq1_0g8kallak8gzg47b5445b74g | |
0b110100010_111110100_000100000_001110100, #xq1_18mcsak8gzg2d67a521 | |
0b111100010_111100100_010100000_000100100, #xq1_g1kssk1gz025bb52 | |
0b110110010_111110100_010100000_010110100, #xq1_4qttq4z932239 | |
0b110100010_111110100_010100000_001110100, #xq1_4qttq4zh5665h | |
0b110100010_111110100_010100000_011110100, #xq1_4qttq4z13a2114 | |
0b101100011_110110100_001100000_000110100, #xq1_27mut2o4oz4e67b421 | |
0b111100010_111110100_001100000_001110100, #xq1_4ts8y08st4z125blaalb521zy111 | |
0b101100010_101110100_001100000_101110100, #xq1_8kqlli8gzi7579774g | |
0b101100010_111110100_001100000_011110100, #xq1_10u4reu5q4ozg2d77a5201 | |
0b111100010_110110100_001100000_000110100, #xq1_0g8ka55ak8gzg4779559774g | |
0b111100010_111110100_011100000_011110100, #xq1_10ucsak8gzg0f67a521 | |
0b110010010_110100100_000010010_000100100, #xq1_y1gy14tc2sgg8gz080g13aeli0cril669rkjz13vgbi3thh5nt862djd4q6dicz8162rjkta82825l09rp5na90gzx1ui56696y140lcn8b343zy0v0dicy29062t3diczi0c5na90gy2i0c5na90gz40ogn8b343y140ogn8b343z1w2v1q4oy290g2v1q4ozy0v4ihg8gy02g1lqna90gz80g2d5mt9a180gk08cegn8b343z02t5b70u54hktai0q7qifhq4oz2b3431bqm62re4lhibek5121zy02711210gvp2t56b43zy8201 | |
0b110010010_110100100_000010010_010100100, #xq1_x81sk1gw8y48wg1ks18zw801ilmb9jeoc8w8coej9bmli108z14bml96s794sho6cc6ohs497s69lmb41zy24geqn4lliwill4nqeg4zy41221038mm8301221 | |
0b110010010_111100100_000010010_001100100, #xq1_40lcq4oz20alv5kg8gz80alvk5121z40l6b43 | |
0b111110010_111110100_000010010_000010100, #xq1_g2f2gwg2f2gz025ak44ka52zy111 | |
0b111110010_111110100_000010010_000110100, #xq1_g4a55ak8z4cb89gmo9z1y12 | |
0b111110010_111110100_000010000_001110100, #xq1_04qllq4z93222239 | |
0b111010010_111110100_010010000_000110100, #xq1_082ll28z18333381 | |
0b111010011_111100100_001010000_000100100, #xq1_ivccicz01 | |
0b101010010_111010100_001010000_001010100, #xq1_09ck1gz8corfb32 | |
0b101010010_111010100_001010000_001010100, #xq1_09ck1gz8corfb32 | |
0b111010010_111110100_001010000_001010100, #xq1_0g4appa4gz2g676676g2 | |
0b111110010_111100100_000110000_000100100, #xq1_cicdc0izx1 | |
0b110110010_111010100_000110000_000010100, #xq1_80afs0gzw90gfg96z105f3 | |
0b110110010_111110100_000110000_010010100, #xq1_4qppq4z932239 | |
0b110110010_111110100_000110000_010010100, #xq1_4qppq4z932239 | |
0b110110010_111010100_000110000_001010100, #xq1_8sg8cotg4z259952 | |
0b110110010_101110100_000110000_000110100, #xq1_02tdq4z4112114 | |
0b101110010_110110100_000110000_000110100, #xq1_9063mit2o4ozx2633421 | |
0b111101010_111010100_000001010_000010100, #xq1_w2bc4isgz080gpwim1s24oz136w15mk4121z040oabkhk1icz01y1id1z0906kka2b1icz0gow18ra90gz1502611iq0fg96zwgkd8ie21zx1 | |
0b111001010_111010100_000001000_001010100, #xq1_y1g4a99a4gwg4a99a4gzw4qiai11192222229111iaiq4z26c140m3siq4y04qis3m041c62zy382eh6iwi6he28zy44114y04114 | |
0b111101010_111110100_000001000_000110100, #xq1_4m38o48gz0gwg0fg696z26c1121 | |
0b111001010_111000100_001001000_001000100, #xq1_0i0curoz26qq324oz2b2iuqpz020136 | |
0b111001010_111100100_001001000_000100100, #xq1_g4qakffkaq4gzw2y22 | |
0b111001010_111010100_001001010_001010100, #xq1_8oaus77suao8zigd041140dgiz41c62w26c14 | |
0b111101010_111110100_001001000_000110100, #xq1_14ss41z14aa41 | |
0b111001010_111110100_011001000_001000100, #xq1_20suroz20136 | |
0b111101010_110100100_000101000_000100100, #xq1_4com68s2hh2s86moc4zx9ovh5665hvo9zx2x2w2x2 | |
0b111101010_111110100_000101000_001100100, #xq1_26crrc62zw2w2 | |
0b111101010_111110100_000101000_000010100, #xq1_1j66j1 | |
0b110101010_101000100_010101010_001000100, #xq1_y74dkeb80gkgozw80goy12g1ltk91b36mgz0h3dba28ctsqa828q8i3n7d1z0gkg575igqocd1051pssm6z04nkjx1513xirq201zw4nkjy1906fpmm6zx4nkjgggggggggpdcz906fpdd11111hlhlmvptsmgz80gocrr333b35lh5hiqocd1z20136m6m6bb3jm6w1513zwhomqa826n7d1zx2013 | |
0b110101010_111000100_010101010_011000100, #xq1_wogkg08bekd4zgm63b19ktl1g2z1d7nj28aoaaea08zw6m63bbc8w69f9zwcd7nmohy069f9z03reecg2y269f9zy01ddpoooooorrjuc0izx69f9uos02g0mmpgzwgmstp82a3aaea02zw1dcoqgi5nlg18zy0315102qe5m4 | |
0b111101010_111000100_110101010_001000100, #xq1_40ostsmgz2b2iocd1z020136rroz0i0cujm6z26qqopdcz1w1513 | |
0b111101010_111000100_001101000_001000100, #xq1_woruc0izciuizw6muc0izx1 | |
0b111101010_111100100_001101000_000100100, #xq1_0cooor6c8z3rccfcgob3m4zy131 | |
0b111101010_111000100_111101000_001000100, #xq1_i6svvs6izw9339 | |
0b111101010_111000100_111101000_001000100, #xq1_i6svvs6izw9339 | |
0b110011010_111100100_000011010_011100100, #xq1_g0kdoao4ozw2b2jd1y78qgkg8gz0h0lrmqmqmqmqmro0105m56r21zw8qgkg8gy120amqmqmt4oz105m56r21y11glhicx1z020amtkcksk5020ad6l796z0h0ldoalv44hicwhzx2b1512a0adbdbdczwh0lrdbdbjwg0kdoao4ozw80amslcq9o8oo23235pzy01502g1lava0amqmt4ozy480alv54hlgigh8gzy180aok512a0ad6l6bi1zw8qgkg5m3a25l0lrmqmqpzh0lavaa0amqmqm6y08qgkg8gz80alvll0ldoaokjgghg5656bi1z40lava282b1503alul1kckcq9gz20alvll0lrdbdbdafq02b15121zh0lava28q8pmgz80alvlg5m3a343z40l6b80amqmqmqmqmqmqe96zy11glhicy28q8pmgzy020ad6l796w105m3a343zy31 | |
0b110011010_111100100_000011010_111100100, #xq1_g0kdoao4oy98qgkg8gzw2b2jd1x2gslsicw105m56r21z0h0lreaeaeaemg020amqmqmqmt4ozw8q8pmgy1201glhicy11z105m3a343y120ad6l796zyd1 | |
0b110011010_110010100_000011000_000010100, #xq1_g4aic370e6s4gz4c3vgw18328zw2w2 | |
0b110011010_101010100_000011000_001010100, #xq1_80qgo1s41wgz011035jsgu4e82zy41105b8hs41zy114sh8ggi8530sogzwi3cu011x2uo452zx2543ce0so69a41 | |
0b111011010_111010100_000011010_011010100, #xq1_gos0ec3iyci3ce0sogz0g2e0s8r3iy8i3r8s0e2gzw25i7kh033ao0gwg0oa330hk7i52zy08q3488843r8118r3488843q8zy04b97ot0fd348843df0to79b4 | |
0b110111010_110110100_000011000_000110100, #xq1_14sho0gz28ll82 | |
0b101011010_111000100_001011000_011000100, #xq1_g4s8euknfcmmcfnkue8s4gzw20731b02w20b13702 | |
0b101011010_110100100_001011010_010100100, #xq1_wg0oggo0gxio3ee3oiy2io3ee3oixg0oggo0gzx283foqdbvbd7o0qg7tbfrrfbt7gq0o7dbvbdqof382zy114h7s6vxvlm6eb025520be6mlvxv6s7h41zy1hkrrfb0rg61mvy8vm16gr0bfrrkhzw81sjmd7o0gfdj7tbo2g0oggo0g2obt7jdfg0o7dmjs18zx129nn9vw11wvadrpeg33geprdavw11wv9nn921zy5vjee3o6pu0h1w11w1h0up6o3eejvzy5var375ujo2gy4g2oju573ravzxg2o8s0761m0b0m1d3c1oggo1c3d1m0b0m1670s8o2gzg1k17hcpodg40m1m04b6ut4vv4tu6b40m1m04gdopch71k1gz025jfeivviefj52y01221771221y025jfeivviefj52zy011033011yk11033011 | |
0b101011010_101100100_001011000_001100100, #xq1_80aoklsicz40lav44aauu96zg0kbvjj88svbjz80adnks5p1121zw1w201 | |
0b111011010_101100100_001011010_101100100, #xq1_y1cislsgq8z69equ6288uv168c0izg8r9erl0h21501z1215102 | |
0b111011010_111100100_001011000_011100100, #xq1_g8gkgqot4y1g080kgq8z1ib6l6565gkggjk7dbdbda08z0pqu62xp5uv1w1woru731z0ci3b2xcdbfc80kgggmj7m4zciebdrtr501w697l6detizx102051y5102 | |
0b111011010_110010100_000011000_000010100, #xq1_040oabcc9kicz01wgy08qr3zi0c5566i596 | |
0b111011010_101010100_001011000_001010100, #xq1_xcoa080kqk432oom4zcvid0jb54755po8866q8z6vm90vy2gm9xgz3f4bgcda2uqq911hmm51zx3150102522c41162 | |
0b101011010_111100100_101011010_011100100, #xq1_283eue382y0283eue382z4gdopkpoooooooopkpodg4zw14bb702jeej207bb41zy611 | |
0b111011010_111000100_011011000_001000100, #xq1_08ogssoeecffceeossgo8z1050e75hy2h57e0501 | |
0b111011010_111100100_011011000_000100100, #xq1_8qgk05sqkg8gz2b150k7b5121 | |
0b111011010_111010100_011011000_001010100, #xq1_0oek58c0izjvvw1z17ta85c0izy01 | |
0b111011010_110110100_011011010_010110100, #xq1_g0ohs41ya14sho0gz02830admuu6uummuu6uumda0382zwg1fc5h6vgf4bb4fgv6h5cf1gzx2552w2594kk4952w2552zy81221 | |
0b111011010_110110100_111011010_000110100, #xq1_y680gwg0ogg4688k8uss44a4veeih688o8k8uss942cggg8gz80gkt828k8ushh9a1jnv7b80gkt8a0i0c8ok8usuvjwg1wid1wiruk1icxg0ogg4g8gsoo2o4oz201w2tu6w137e03suvu5201w2tuusuvv6w13701uvvn1gosuvv711210j1r8fn7332235p0m4tocxgosuv84ousc1ciczy2vvjy4vvjy4vvvvvvvvsgg8g0o7f12173dh7jbgosuf3x807osuv84306235osuvvvvvc1114qstoczy2vvpy4vvpy4vvvvvvvv7112103sug8gsomhspq137fuox20s37fv24o0c8ok37fvvvvv6ggg4b7n36z80gw8nfcwgose0o7fvfk80gw8nff7fvvcwgos0gfvvtg137fvvsgg8g0pgr2utsoo88okj0d4n36x137fv243f76g696z2015n28252f7hhiagptvsq2015n2a09062352f7fvpw1gw9mgw9rf5g96x1031141217338343zy6201w103114c2252f7744a4vee9hc223252f77i48611121 | |
0b110111010_110010100_000111000_000010100, #xq1_0i0c85kuozxg108qr3z9062k5f3 | |
0b110111010_101010100_000111000_001010100, #xq1_y8gmsl04zxg08wogk05beaqskk609z0ounldebr2e7l04w63a02z3rea08zx1 | |
0b110111010_111010100_000111010_101010100, #xq1_y3g4a99a4gwg4a99a4gwg4a99a4gzwg84i222911922222291192222229119222i48gz82odt0pes4gygg4sep0tdo28zy020b1301u9t2y82t9u1031b02zy282e4f353f4e28y082e4f353f4e28zy41y31y41y31 | |
0b110111010_101010100_010111000_001010100, #xq1_y040lsmgy1gz906kcss2i335lft43z80aer30g1ltn6zw1y2201 | |
0b110111010_111010100_010111010_011010100, #xq1_wgy0gwgx4gt8sg8hs41yg14sh8gs8tg4xgwgy0gz28e4uokou2y4113vngo0g0ogq08y080qgo0g0ognv311y42uokou4e82zy21vrosg8hs41w80n1jfne3bo1hy2h1ob3enfj1n08w14sh8gsorv1zy2254317hvda03u70oa32x122a2kkkk2a221x23ao07u30advh713452zyd4bjjb4y5124421y54bjjb4 | |
0b110111010_111010100_110111000_011010100, #xq1_y24qppq4zx8oss30svuskggz41n3tbvwvn7e1b02zy02xv77v8t3n14zw8ogscmfvx2z010501w4114 | |
0b101111010_101010100_001111000_001010100, #xq1_gy040lsu8gz403aqueow201u080gz010513y190gf0fg96zy9v090gz080aos0gx90gf0fg96zi0c5577hgg4g8701zy120a371 | |
0b101111010_100010100_101111010_000010100, #xq1_w40lsu8gzw20aoqg4b80gz40lstttsttv71z080aeeeeeeeuozxh0l7n29l513zx80aeu421zy11 | |
0b111100101_111110100_000000100_000110100, #xq1_15kcgl50ck51zwg4ilabk4z098m98zw98mkba2zx1w1 | |
0b111100101_110100100_000100100_000100100, #xq1_y1g8kqdcccc7cizwg08hlcjcjcu1zwh8amc3781w10g8kqdcccc7ciz6lifg3adhp54444hlcjcjcu1z0125bmcph47u0pait3c37801gzy2125b31w125b3333e34 | |
0b110100101_110100100_000100100_010100100, #xq1_2so6o7cccccdqk8gz210vmptakoxhfil6zw8vkc1ui8q217foelaczxg13b521y0gocna53zx43e3333333b521 | |
0b111100101_111100100_000100100_001100100, #xq1_0g8kqdocogzcl9uhwpat72zw125b31w1 | |
0b111100101_111100100_000100100_011100100, #xq1_wokqdocizgmq4v0hz125b134 | |
0b110100101_111010100_000100100_001010100, #xq1_02so5ak8gzwvkbi01ul6z4obte4alak8r0oz1w1w103060d103 | |
0b111100101_111110100_000100100_000110100, #xq1_w9amah8z08ac154z11 | |
0b110100101_111100100_010100100_010100100, #xq1_g02sncssctakozgfqdepepela6zw1y021 | |
0b111100101_111100100_010100100_011100100, #xq1_02sotakozic7cna6zx1 | |
0b111100101_111110100_010100100_010010100, #xq1_0g8228gcppcg8228gz04kbi11111111ibk4z2hadah2y02hadah2 | |
0b111100101_111110100_010100100_001110100, #xq1_2sotakoz210306 | |
0b111100101_110100100_001100100_000100100, #xq1_okatcc7ciz06ale7666s69zxg9l4xo0gz0obitjn3jb134zw12511712 | |
0b111100101_111100100_001100100_001100100, #xq1_8sdqkoz8sofka6zw21 | |
0b111100101_110010100_001100100_000010100, #xq1_y2880cppcg55gc99cg55gc99cg55gcppc088zy1gg1lk1h48ye84h1kl1ggzy02s0u10j7644gw88w88w88wg4467j01u0s2zx4kb49ce8hw4kbk9hcj66jch9kbk4wh8ec94bk4z84ala59y542324y042324y595ala48z021112yu21112 | |
0b111100101_111010100_001100100_001010100, #xq1_x8hamah80qskizgk5had29831ab022zw4511 | |
0b111100101_111000100_011100100_011000100, #xq1_w8g0octacy2gk8gzgogvjn6767br3333jn51oz015lihgocddcccsuao1z027lh91b530gx21z8sm666efdceulmgggoqkozgoqqpotacw4lp1119bi0cz01521gf6vjvjm66eflczy51521x1 | |
0b111100101_111000100_111100100_001000100, #xq1_08stacy4gz4eeeld1111119tkgjggoqkozw9tscsctacw4lp1119bi0czwgoqpoonm77776666flcz013a840lihggggggkl9gzw4eb3jn7nn77br337lh80gz4eb3j3na6w18tcssssuao1zw9tssuueeum6na6x21zy021036na6 | |
0b111100101_100010100_111100100_000010100, #xq1_x8hamah8w8hamah8zw9h6pq5a2oo2a5qp6h9z125hsvvg7offo7gvvsh521z0h2f7b1k2gwg2k1b7f2hzw1441mk3gqqg3km1441zy51441 | |
0b111010101_111100100_000010100_001100100, #xq1_0gklmml4c2rm84zg0of8gnlkgy18acca8z01230t0aho7d1791v11v11zxg0fg8x45t44s90fgz08aqbbp5dk4s4jgcr3as642zw29831642w12560cb521 | |
0b111010101_111100100_000010100_001100100, #xq1_0gklmml4c2rm84zg0of8gnlkgy18acca8z01230t0aho7d1791v11v11zxg0fg8x45t44s90fgz08aqbbp5dk4s4jgcr3as642zw29831642w12560cb521 | |
0b111010101_111110100_000010000_000010100, #xq1_48l66l84zx22 | |
0b111110000_111100100_000010000_000100100, #xq1_cidc0izw1 | |
0b111010101_111010100_001010100_011000100, #xq1_06lsogzobqj1zcl731 | |
0b101010101_110100100_001010100_100100100, #xq1_y142tro62k06qk8gyuggy3g44gy2g44gy3ggyug8kq60k26ort24z84qmgkk7i3cmgd8anck8gs4o0g8kqt306qk8gy5g8kc0oicgmc3ha0n0ck8v8228v8kc0n0ah3cmgcio0ck8gy5g8kq603tqk8g0o4sg8kcna8dgmc3i7kkgmq48zx1089e5h1p4g0o8v50s23sd590dfrvmu10g8kc06qk8gwvrf04237e6v6e75f50doaaod05f57e6v6e73240frvwg8kq60ck8g01umvrfd095ds32s05v8o0g4p1h5e9801zy2153lsm05v8o17131v10u1w10u1947491ergmngoognmgmq48yo84qmgmngoognmgre1947491u01w1u01v13171o8v50msl351zy41xv01j7oc194744744gwvy221131x131w1yu1w131x13112y2vwg447447491co7j10vx1zy342dr8acvcaj1x42dr8acvca8rd24yzyl42dr8acvca8rd24x1jacvca8rd24 | |
0b111010101_110100100_001010100_010100100, #xq1_08s5acwgk8g0oy18s5acw8gzwgf9kd1v851kj1thh5pvdm87v1q3wg0kow8gz27vcnu6senb52103w1521y1v99t4smprhril6z01w9tiapyd1wv999t4hjqulkozy221yg10gf4fu3pd8dka6zyt1w1w1 | |
0b101010101_100100100_101010100_000100100, #xq1_ygg8ytgyzyfca5s8wg8kgzwg8kqt4888u0ca5s8832pvqo0g8kgy1g8wca5s8y56lie4xca5s8xokaogxg8kgy1g8y7gy1ca5s88ulg57mhec8dd0vpgz0g9l4e44lear4c703q9hl3vrjghtkjpo8e5qj1be76hus88888u0h2ad46s024lr8co048amhog08hlc3hwg3ap72wg8kg0ml2u4k444vl4eeve4eeveeve44vvl4z3q9d6fj4444l4e4x12510ik51bppvg80bfc8d7ejght1em263010211170304222f0609544v0c0ib99v0o15mijua39ehhht0f34w6ak722fl1ksdhe62mm0vj1zg0954444444l4e4y4125b2117095444k4f55g5s8ywh08454k4f55g5t81yc6ak72w1251z10ik4444444l4e4y4g8kq8ggs0ik44454ukk1k72ywh024k454ukk1kn2gygca5s8wg8kgzobimcup4444l4e4xg8kg095kgqjjv120qu62msep1hnged8co0g08gggs0o04888u0c0ik44v0609qiiv03gkd9pfaoiehhhn0uo4y2ca5s88ulg57mhec8dd0vpgz01il4e44lear46s0obihlovrp1hn5pj32ekbpgqeschf722222f0h8am4c7084lr263042adh3102hl6ohw1oajs8w12510dl8f454444444vl4eeve4eeveeve44vvl4zw125bn4222f06ak722o8jvb301251y112w6ak72y5cl9e4x6ak72x35a31x1251y112y71y56ak722fl1ksdhe62mm0vj1zyg12yt1yzyj6ak72w1251 | |
0b101010101_110100100_101010100_100100100, #xq1_8s5acwgz4vel4igq7c4dakoz27ka6w9t4higaczy24ogn7i79qo4dakozy2973rpjp5n79qoik08gzy34up32jlsgg817dv1q3zy313suagsdka6w27ka6zy1icv0r328a9gw8gzy18sjao22aviia17m5aczy321y08av999bhtqk8gzya13auui8240lpzye973r13a840ozye8su7b3i3lczyb8av99994tcka6zy38s5acw8s57a2iniapzy34ov1c119b9512b521zy31030vv94tqk8gxgk8gzy5ivc114ku4590gpv0d1zy48g1ef5fikg8ce7m3a53zy4if7ni7iaffip8lczxgk8gw8sj757apw21zwhvolh44eioip8lczw8vhao1053w21zy021 | |
0b111010101_111000100_011010100_001000100, #xq1_w8gs6fe4s4ef6sg8y28gs6fe4s4ef6sg8zy5vy1gosoggosogy1vzxgogw870egj410v0110v014jge078wgogz24713317ie2qev3m078w870m3veq2ei71331742zy522w11y011y011w22 | |
0b111010101_100100100_011010100_000100100, #xq1_48mr2a6v6a2rm84y2gy5g0oc88osogy4gwgy7gy4goso84zy2144s90r1buu66utpjgmok6c0oc5e3k1gfr0mut44su773d4o88osen6kol7d0c6kk6nfh90r1m2a6v6a2rm84zy3125bc05831bglom6oh1f7eq17430sddsq850t0tn3rq26hmfgwgfr065210vy011xvw9s441zybh1vn1agj41034712882fvk0r1r0r1db42e9ui2upb63n0c6fma90v048osuck971cb521zyc12560qf7q88oso8acch7vh1v11y224bmo1cb521034amfv35henb521zyf125bc06521032174301441yj123011 | |
0b111010101_110100100_011010100_010100100, #xq1_g8kgqpscvoe0sg8kgz1d0v69mcuudi3bodnupgz35a31hn532e1jkr3731zy1125bnhfd379zy46ak72 | |
0b111010101_111100100_011010100_010100100, #xq1_wg8kgy1ca5s8z6l2jb095hhtkpvgz3qs4strv731r3t7v2z6a19h5m7feseutf72z35ame845445hk7ogzy01y21251 | |
0b111010101_111000100_111010100_001000100, #xq1_0gosl6z973vts4daczxvvvd11i0cz4ogvff9dlcz137fbo01zy01 | |
0b111110101_111000100_000110100_001000100, #xq1_8sl6zwiq906zx153 | |
0b110110101_100100100_000110100_000100100, #xq1_08s5acy2gzxv9kd1119t4gjgggggk8gz272mlcy0in41p11119t9ajz04u2o2222240lkoxgogcb25mgz013a8i222222s8dlb70e332b521z272rl9gy010872qk8gz0go7kh5480gk8g0on41lkozw15210g0273s5764e9lqsggk8gzy14eil6wv9999ag2codkh9q3zy3v4arem5acy1gk521zy14e9lcwv99a840ocom5aczy31y0viiip8lcs64ma53zy0gk8g0272qfd8tiapzx13s5hk4201y021zw2s8rli1zw1g02a9gzx872rl9gzy0go7kh5480gy08gzy1152108s8bum2n9ajzy4gy0v999j2l67c4dakozy24eil6wviia240363dka6zy4v4aredka6y115k8gzy24e9lcwviiiia1863m5hibozxgk8g0108so7ksc4eilb711521zw13s5hk420152103t4gl53z08s8rli1y0g02s8b521zwgoa2988888872mlqs0eoo8qk8gzw4f838888840l53x1316q8kd1z08s8dl6y09t4gjgggginiapzy0vi5mgggin41p11111521zw27ka6y21 | |
0b110110101_110100100_000110100_010100100, #xq1_y7g8kggsqls8zy6ja9t81wcaqgo4y2g8zg8kq8gggm5ivy2g3ajmebiscknul72z1dk8qjpun5po8pi222f06ak76tdlt81zx12x301251y812 | |
0b110110101_101100100_000110100_001100100, #xq1_w42droaaord24zx2abqpdu3g6qk8gzy0216d45noc1p4zy4g4knl468rd24zw4p1cod0qv2y0vz0ggvg44g0ff0g82qba2z84qmglohnrl5111112zx1y31 | |
0b110110101_111100100_000110100_001100100, #xq1_wgwg0oclqsggk8gz4ogfirgna6w18t9ajzgf4phdacy4vir8os5acz4ogc7oboy4v4cbcvgbozgf4q6e5k8gx8s8b53x21zw43170fplcs64ma53zy521 | |
0b111110101_111110100_000010100_000010100, #xq1_x84h1koggok1h48zxial9gy0g9laiz84hc522864468225ch48z0272y8272 | |
0b111110101_111110100_000100100_010110100, #xq1_2s8o2k70cz872385s06 | |
0b111110101_111110100_000110100_001110100, #xq1_30e8s8z30r8s8z301 | |
0b110110101_101100100_010110100_001100100, #xq1_042tfoqqoft24zg9ltu1w1utl9gzw15f4114f51 | |
0b110110101_111100100_010110100_011100100, #xq1_8sou0v4ki0cz273q33233b53wgzw431thhhhhphtsobozy02103b53y021 | |
0b110110101_111010100_010110000_010010100, #xq1_012uqqu21zik763367ki | |
0b110110101_111100100_110110100_001100100, #xq1_x8s5acz8souu1tacz273ffgna53zx27ka6 | |
0b101110101_100100100_001110100_000100100, #xq1_x8s5acwgzwgwv9kd1wv44ki0czgognai1w4e4lvv1qmgz018tpa3888s8nkstiapz0hlvv0roookg3x21z08avv0mmmmmlcz04lvv0ddddddtb8gz02avv0roooookgjm5acz0hlvv0m6666mib34ma53z08avv0dcccccuq0sggk8gz04lvvgbox131uijbklpzx1ge5k8g0272qffol6zy2gf92b8g0f222403zy113a53 | |
0b101110101_110100100_001110100_010100100, #xq1_y0gy6ca5s8zwj0kt911111h194lr8s8z6l2usm4e4444l4e4e40ae4zcl8vsngoggjg4t9y06ld8s8zw12511111p14nigggm5ivzy81y26ak72 | |
0b111110101_111100100_001110100_001100100, #xq1_048o88o8if2oo2fi8o88o84z45t930h1xvvx1h039t54z125bc179ks2bb2sk971cb521 | |
0b111110101_111010100_001010100_001010100, #xq1_w8s52qea9z125ap6sg811z04511 | |
0b111110101_110100100_011110100_000100100, #xq1_ya8s5acwgk8gzy28gy1gwv9kd1v851ozy027pa38888872qpo8s8rl480gk8gzxgogna53wiv1ccecececececlh9q3z08s8dka6y115ki0cy14e4li1z4u2opookg80gw9vg6666667mb521z13a840l4iegnai22403ziv1c11j1dcv0d1z0hl491b9js3qljgg80gz9vg6667a2403w4u2opoooooqk8gz04e4dakoy29bi0cy018t9ajzx272qk8gwiv1ccscscscscscb25mgzy0go7kh54445pgm664e4ma8403b521zy11521y0210u5ac0u5906zya4e9lc113a53zyc1 | |
0b111110101_110100100_011110100_010100100, #xq1_xgy18ggg81qeaaeq18ggg8y048o88o84z24bd1m2qma430ue0kvvw220v022u29831tth3op2ei9o88o4mcg8zw48mr2a62c4p7d0avvk0gwvxvwgwvva0lv4gg9qb8eo1hzy411x1441vv0ip850c7c0dgj41vv5gh43014410321zyb24bmo1cb521034amp3gdn84zyt11 | |
0b111001101_100010100_000001100_000010100, #xq1_04lmkki0czw8aq3z4ld55906 | |
0b111101101_110010100_000001100_000010100, #xq1_04p1s88zg8v0vg01u44gzw103070o4vzy242f0712 | |
0b111001101_111110100_001001000_001110100, #xq1_gk5uu5kgzx22 | |
0b111001101_101010100_011001100_101010100, #xq1_y2o0rouosqogzwc0oeusoqvtourvjca8z30r3fbb90vavtoruf63lhzwg0snvecvdf6310o0ervjca8zw1o0r34w1y0g084554dl4zwc0oeu1y1c0dciz30r3frvy2o0ro4zxc0d1iy3609ggggokgzw60snvoosqogxc0oeu4qa8zwc0obb90vavtfesog1n7301z30r3frvucftvesft7pba2zy11d0cdvesdf7301zy4301w1 | |
0b111001101_111010100_011001000_011010100, #xq1_wgoqsouor0oz1utruotvqosueo0cz0vvcvcvcvcvcvdcz0vfmv6fun6fut70cz1037me7v6m06zy51 | |
0b111001101_111010100_111001000_001010100, #xq1_4kgttgk4y64kgttgk4z042fvvtshp4y04phstvvf24zy1137nadfeefdan731 | |
0b111101101_111110100_000101000_100110100, #xq1_2sns06z103 | |
0b111101101_111110100_000101000_010110100, #xq1_2sncgm0gz87t61d01 | |
0b110101101_101100100_010101100_101100100, #xq1_y3gko6okgy08asksa8w45uqelkgyagy145uqelkggg8ylgko8okgy0gko8okgyl8gggklequ54y1gyagklequ54w8asksa8y0gko6okgzw45uqlnpj1r1jpmefnlqbns88sdu9vdgjpdrblrblrbdjbt36imlcckqv5pmjbufh9y2gklequ54y18ask6e2drbokgwgkobrd2e6ksa8y145uqelkgy29hfubjmp5vqkcclmi63tbjdbrlbrlbrdpjgdv9uds88snbqlnfempj1r1jpnlqu54z45uql7f5fs76tev7j7vo0gpcr7cvudaro9cbqdlbevahnt4c6rldq5rmalrbrl6kstlbrlbrdpjgdv9uds8ggocmblqu541fj4y04jf145uqlbmcogg8sdu9vdgjpdrblrbltsk6lrbrlamr5qdlr6c4tnhavebldqbc9oraduvc7rcpg0ov7j7vet67sf5f7lqu54z0gfvtqmbrrtitms4rcog0vv0g1k3gufakrvisc5trm7cvu01iors46ufafutm1781su38bsk6e2dncfedqbopsba3f7lq6rrblquuqlbrr6ql7f3abspobqdefcnd2e6ksb83us1871mtufafu64sroi10uvc7mrt5csivrkafug3k1g0vv0gocr4smtitrrbmqtvfgzw2983us18buf7eusc5ds88sn045vq1760tg33gs0330tg33gt0330su330uv11wvvxvvw11vg11gu0145ucs561r1760t0220t0671r165scu5410ug11gv11wvvxvvw11vu033us0330tg33gt0330sg33gt0671qv540ns88sd5csue7fub81su3892zy64jh63dd36hj410330671288210330128821033012882176033014410330671288210330128821w2983166134gg4316613892w128821033012882176033014410330671288210330128821033012882176033014jh63dd36hj4 | |
0b110101101_111100100_010101100_011100100, #xq1_y5g0ox2sncssq840oz04oeoooookv1vnj7qdlg3fvtk0ox8gsgg80gz1urtup7s7ssrtup6t7t6qop33335vtos776qo1z43ulrsvpv9p6tbc3tndb2gsue6u575g9vfbi0cz0103y197s7767qdlouvn51oy21zyb217111201 | |
0b110101101_111010100_010101100_011010100, #xq1_w24v0mo74qogy0gwgy0goq47om0v42z24vwhfu6v216bt330aa033tb612v6ufhwv42z0gf0g024vmjesgj4y24jgsejmv420g0fgzw227gj4w1154y64511w4jg722 | |
0b110101101_110100100_110101100_010100100, #xq1_yagyvo048qssssssssssssscsscsssssss7sizxgxo0gmgpam77777j7vfvvjv7bfvvvfvvvvfnvvvvvvfv35nqrff71aj7lrj1bfvuvo1ljr9mffffjqtscsss7si88888e8kgz03gkdrhrva67n7jtqauqnmnnm2nuviu70bjmeeecrff7rvvuvvsquvtuuuuusuvvutvvvvvvuvvvvsgaptuuusuvvvvf3l55575uckknka8zg095644745ghgikcfri2b77jnffffffedfffeohquvvutvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvpvsquvvjv712w301z10ikc44s4k1h1956ur98qssptuuuuuuemuuue3hbfvvfnvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvjv7bfvvpvsg8wo0gz0o15mrhrvacstspnbafbtdttd8tfv9fs0qpdeee6ruusrvvfvv7bfvnfffff7fvvfnvvvvvvfvvvv71ajnfff7fvvvvuolkkkskf655t5a2zx1x301d1jadssssspsvuvvpvsquvvvuvvvvutvvvvvvuvoktbruusgapslrpgquvfv3glpriduuuupbn76777s7922222e251zya1yv3042b777777777777767767777777s79 | |
0b110101101_110100100_110101100_110100100, #xq1_x8aknkkkkc9agsggg80gzwg018b8gsulnlft8d6qo1z1ur6eedkg3wg2q322bi0cz0vmvpiopnaeaad5lt3q2240oz0vdvjvvrvsvksptsnq82a9gz0vrv7vvfvvvnvfvvnf8388403z0vmvf7ffn8r88qikv1c11i0cz0vdjqpom711152e223951oz217119a84vskklpv9pjdczx8aknkkklqba7u465906zy0103y121 | |
0b110101101_101100100_110101100_001100100, #xq1_0gwgoqsjsqoggoqsjsqogwgz22vtqdeputm1661mtupedqtv22zwvvvfg9srqtvvtqrs9gfvvvzwvvvvm3bbt3bb3tbb3mvvvvz014jh73cc278w872cc37hj41zy811 | |
0b110101101_101010100_110101100_001010100, #xq1_y448u0no6g4oo8oo8oo4g6on0u84zy424h6djlgcuuvssvuucgljd6h42zy148u0cgl8ppubjjtrrtjjbupp8lgc0u84zy2iper56fvvnj2dq66qd2jnvvf65repizy09avlimuvvvvvvvnjppjnvvvvvvvumilva9zy4hfjnvvvvvvvvvvvvvvvvvvnjfhzy0gocmmqtvvvvvfv7fvvf7vfvvvvvtqmmcogzwh2fdqtvvvfvvvuehqnmmnqheuvvvfvvvtqdf2hz12vy0v1034udt5ros6rr6sor5tdu4301vy0v21z04jgsejmviscvu0nqhl4gg4lhqn0uvcsivmjesgj4zy011u301vu011ujb33tt33bju110uv103u11zy1298u0110u89206811860298u0110u892zy51441y311y31441 | |
0b101101101_110100100_001101100_010100100, #xq1_wgg0o4114o0csg8228gsc0o4114o0ggz02s86r4tlcjemvp8ee8pvmejclt4r68s2zwv4kfgfk4vwv10vv01vwv4kfgfk4vzwvx1880v88vs4nn4sv88v0881xvzwvx1u43t17fk4vv4kf71t34u1xvzwv4phcn5tfsc071oo170csft5nchp4vzwv0vggv10j7q2ogffgo2q7j01vggv0vzwv0v0216vc2f0f0gg0f0f2cv6120v0vzwv0vw2a7oshiwvvwihso7a2wv0vz2a7o7a2y01u0u4334u0u1y02a7o7a2zy6153c351wv0vzyd153c351 | |
0b101101101_101100100_001101100_101100100, #xq1_wgg0o4114ogccgo2i8wggw8i2ogccgo4114o0ggz02s86rsdtcv88wvgg0v2112v0ggvw88vctdsr68s2zwvxhjtu53kve1ig0f0gg0f0gi1evk35utjhxvz2a7osigu31g5o1f0hjuf2hh2fujh0f1o5g13ugiso7a2zx4puq567467kc8ff8ck77kc8ff8ck764765qup4zw1532351ym1532351 | |
0b101101101_111100100_001101100_011100100, #xq1_y3gwgkleq6e2e6qelkggko8qckscktmameq6ei6u265ss562u6ie6qemamtkcskcq8okggkleq6e2e6qelkgwgzy0goqandpjgbu265scktb6132uu4410v220v144uu441vu0110uv144uu441v022v0144uu2316btkcs562ubgjpdnaqogz045u134hno8cbfbroi10uv11wgfvgxvgwvxvvxvvy0vvxvvxvwgvxgvfgw11vu01iorbfbc8onh431u54zgkoj1uu26jdarfphgfvo1hvug33vbhmlsqv781q0770pscj72ss27jcsp0770q187vqslmhbv33guvh1ovfghpfradj62uu1jokgz087vcg8srvrsk6uq3n3absp0770cetfaqnun2cbksqvmnbrr8pp8rrbnmvqskbc2nunqaftec0770psba3n3qu6ksrvrs8gcv78zw1441fg22gfvg0os7gocr7di63fd16613963d7uo1ce3rv681186vr3ec1ou7d36931661df36id7rcog7so0gvfg22gf1441zy422w11y011w22y711y811y811y722w11y011w22 | |
0b101101101_111100100_001101100_111100100, #xq1_y0gkluqu54xgy4gx45uqulkgz8as37hioradjbt36imlcclmi63tbjdaroih73sa8zwvg0osnuntl6ksrvl8rr8lvrsk6ltnunso0gvz02983u1551r0df2qv681186vq2fd0r1551u3892zy21441y511y51441 | |
0b111101101_111010100_001101100_001010100, #xq1_wgocd2uu2dcogz9av3dm1vv1md3va9zx22w22w22 | |
0b101101101_111100100_101101100_011100100, #xq1_y2g0oy9is7ccccsq840ozwg0o0sf93j33333j3337refkvssssut3q2240ozxvdb2hfq322226cdcqn5444591hprl62q21zxvrdkg8v3r33bjwgon666666elh201z8hub07u9e5fn9f2uonr4reueeeeelh80gz43e3tqb1b63mblc8b8g1fsl444ighjrlc8b8gzy043e333335vgrooooosreu5v777fnob88403zy8103y497s6667b2403 | |
0b111101101_110100100_011101100_010100100, #xq1_y1g8228g0o4114ouuo4114o0g8228gz04phcn8qao7ssgjvs4nn4svjgss7oaq8nchp4zwvwv0v98v0g491s8778s194g0v89v0vwvzwv4kfgfop0nvum05ouuo50muvn0pofgfk4vzwvxv0vvbg3fsvo4114ovsf3gbvv0vxvzwv02a7o77o7a2vvkkvvkkvv2a7o77o7a20vzwvg44gvkkvu6037qiffiq7306uvkkvg44gvzwv0v21603v10uu030ss030uu01v30612v0vzwv0v04phcn5tvrgck77kcgrvt5nchp40v0vz4kfgfk4vw1wvv1w88w1vvw1wv4kfgfk4zx1088v0g8227t061oo160t7228g0v8801zy210j76pso7a20vv02a7osp67j01zy5v21h4ogck77kcgo4h12vzy3153cuk3j9y29j3kuc351zy64kfgfk4y04kfgfk4zy91y61 | |
0b111101101_110100100_111101100_000100100, #xq1_xgg0o4114ouuo4114o0ggz08isombkd5suvvus5dkbmosi8zwvvvoovss0j77j0ssvoovvvzwvvvvvvvvbgssgbvvvvvvvvzwvvvvvvv5ohffho5vvvvvvvzwvvvvvf3gb0ss0bg3fvvvvvzwvvvvv1uvs4nn4svu1vvvvvzwvvvjgs2vggvvggv2sgjvvvzwvvvgi1u120vv021u1igvvvzwvvvf1oo0nvvvvn0oo1fvvvzwvv70csv3gbvvbg3vsc07vvz4kf70sig01v0vv0v10gis07fk4zxv2160cs7o77o7sc0612vzxvx2a7o7ss7o7a2xvz0ggvw8i2ofgffgfo2i8wvggzw216fq1re523325er1qf612zy02a7o7a2y02a7o7a2 | |
0b111101101_111100100_111101100_011100100, #xq1_o048qssssccccccc7siz0cdjup0gm6c888e8t5bcns2z6095mrspdrescscv12gldvzx6mpgg66no6qnpu27krvz0609gggg6mv0jb194454mvzx6mpgg6mpfpf666666vg9z0609gggg66vgctopi2aimvzx6mpgg6meh6lep74uidvz609qmt3prd73333fo40arvzg3bcnpggm6311171bqt3e34z1021533333333333e34 | |
0b110100011_110110100_000100010_000110100, #xq1_0g8g4q5embkecgogz34b4r4wg9gq253me4zo4q4r4w1i1b8kode4z01214bkedq5e6131 | |
0b110100011_111110100_000100000_001110100, #xq1_wg8kalla88allak8gziteletiy2iteletiz013631y413631 | |
0b110100011_110100100_010100010_010100100, #xq1_8so6nscsakoy1gzgvha907pnhhjbj336dqk80gz4f7orfnufhn7b43xgpffm96z8so7cqpon6s666666b521z273sbkl19ru6uudiczxvcicwvhai01zxvciqgcrlihg8gz2vehm6b52ufhn7b43z0vcicy0vciczgvs2qok8gvs2qok8gz010vcin3cmbj33521zxvcicwv3kjzgogfkaa04nvouudicz4f7odm77rpeooopook8gz8so7msrut2qok8gw136tsq4oz2v3k51p6r33jlihgocmb5121z4f7oredflb71111121zy01 | |
0b110100011_101100100_010100000_001100100, #xq1_w8qn6mna8888oo8888anm6nq8z23vsnbqqtvfg1221gfvtqqbnsv32z025bbrmaaa98888889aaamrbb52zy04bnnbpl5lddl5lpbnnb4zy48nfog11gofn8zy614bnnb41 | |
0b110100011_111110100_010100000_001110100, #xq1_0g8k2tuembmcogz3438nfedqd631 | |
0b110100011_111110100_010100000_011110100, #xq1_4ermeu6u5q4ozx13633521 | |
0b110100011_110100100_110100010_010100100, #xq1_goq7mm7q2amma2q7mm7qogzwvvtmq88soos88qmtvvzwvvvt038mffm830tvvvz025bb52x11x25bb52 | |
0b110100011_101100100_110100000_001100100, #xq1_w8qn6mnaooanm6nq8z23vsnbaabnnbaabnsv32z04bnnb41vuuv14bnnb4zy325bb52 | |
0b110100011_111110100_110100000_010110100, #xq1_4ermueuudiczx10jdicz8smrutvuciczw1y11 | |
0b110100011_111110100_110100000_101110100, #xq1_0g4allqk8z1uvfmqd72z27d72 | |
0b101100011_110110100_001100000_000110100, #xq1_27mut2o4oz4e67b421 | |
0b101100011_101110100_001100010_001110100, #xq1_w8kqllak8gzwiblbalala9k8gz8pu7ul9gdg9lu7up8zw2bul9gdg9lub2zy1136d631 | |
0b101100011_111110100_001100000_100110100, #xq1_0g8kallak8gz9unu9w9unu9zw1y21 | |
0b110010011_110010100_000010010_000010100, #xq1_xg84a99ak8zx8f3iik8gnjhz08oq51x1w4ct2zxhu6c4y1g8f362z4ct2y18ki5ipq4z08on362w4nh948bizx2tc4w8k91cg5u9z263no8sa126e172zy01 | |
0b111010011_111010100_000010010_001010100, #xq1_wg2f2gy2g2f2gz23bkgdmllllllmdgkb32zx8n64la22al46n8zy111y211 | |
0b111010011_110110100_000010000_000110100, #xq1_8coej2w2jeoc8zx12599521 | |
0b111010011_111110100_000010000_001110100, #xq1_08ka55ik8w8ki55ak8z26lla7amb55bma7all62zx15e41111114e51 | |
0b111010011_111100100_001010000_000100100, #xq1_ivccicz01 | |
0b111010011_111100100_001010000_000100100, #xq1_ivccicz01 | |
0b111010011_110010100_001010010_000010100, #xq1_y38ce76kgzgogs801vc244cfhzw1249jb4xgkb32zy0hfci2q96n8zgk673o4jb4licfhzgfm1ik4ibj9421z0147cc741 | |
0b101010011_111010100_001010000_001010100, #xq1_8oqur362zw18l62zit7bc4z026e731 | |
0b111010011_110110100_001010000_110110100, #xq1_4evok6skcciczx13w1 | |
0b111010011_111110100_001010000_011110100, #xq1_4qq4x2tdigz137lkkouf51zy0131 | |
0b111010011_111010100_001010000_011010100, #xq1_2bmau5uozwv0v0vv96z4d657a71 | |
0b111010011_111010100_111010000_000010100, #xq1_4evu61q48gzx1u1idiivcz8suvo1m9421zw1w1 | |
0b111010011_111010100_111010000_001010100, #xq1_08oqur362z26evf51 | |
0b111010011_111110100_111010000_011010100, #xq1_4qp9ak8z137fvf4 | |
0b111010011_110110100_111010000_000110100, #xq1_4u8cevu4z125aa421 | |
0b111010011_111110100_111010000_001110100, #xq1_2tdigz4fvuu9zx1 | |
0b110110011_100100100_000110000_000100100, #xq1_w2tdq4z01vdodv1z131x131 | |
0b110110011_110100100_000110000_000100100, #xq1_27ksciczwgv0m66696z4e23343 | |
0b110110011_101100100_000110010_001100100, #xq1_cicskn2gz0g18at131z343b8vzo4qslm272z01x31 | |
0b100110011_110010100_000110000_000010100, #xq1_0ifcek0gz8s52qj311z4bjjb4 | |
0b110110011_111010100_000110000_001010100, #xq1_0g0oq7u2t24oz1311v871xv96zgoggv2sgxvicz0103bsf8n843 | |
0b110110011_101110100_000110000_000110100, #xq1_4e4raedic | |
0b110110011_110110100_000110000_100110100, #xq1_2buaem96 | |
0b110110011_110110100_000110000_000110100, #xq1_0g23uoc8z9nmb4 | |
0b110110011_110110100_000110000_000110100, #xq1_0g23uoc8z9nmb4 | |
0b111110011_111110100_000010010_001110100, #xq1_wg4allq4y24qlla4gz8pml9gwh5a88a5hwg9lmp8zw26loh654a55a456hol62zy11y81 | |
0b110110011_110010100_000110000_000010100, #xq1_gogafsgwgzgpg69ppffg96z0105f3 | |
0b110110011_111010100_010110000_001010100, #xq1_0272ee6u1icz4e477b701 | |
0b101110011_101100100_001110010_001100100, #xq1_0g2nkssicz131taqfv1dcicz27kbauu4lh8gzwgf9prk5121zwgf9ppm96z8sgf9pt2qo4ozw2t5n7ia81gz8s8rllvv8b343zw4e23343 | |
0b101110011_110010100_001110010_000010100, #xq1_w4qppa48gy8g84appq4z4ql1g56hla9k8gy0g8k9alh65g1lq4z130at4pq4wg8i3223i8gw4qp4ta031zy1g954a549a5445a945a459gzy14f373nppq4w4qppn373f4zy71031w1301 | |
0b111110011_111010100_001110010_001010100, #xq1_go0ana0ogy2go0ana0ogz4bl89k952c2442c259k98lb4zx25ai4ka3ll3ak4ia52zy39ckknnkkc9zy425aiia52 | |
0b101110011_110110100_001110000_000110100, #xq1_02buu1q4oz4d779421 | |
0b111110011_110010100_001110010_000010100, #xq1_gogajm25q48gz0h0la403s25k0jm25q48gz1j1cccccfg9b1icgb4216p4ak8gz131ak80g0kb807o48gc8la90gfg96z272lai01jchakg3ci54g8n843zy0v09m942d46s25q201z8s8521y3id2poo48gz8s8j3333333334q20s3421zxidi8k80goga521gz4e4ihgg961ci983jfg96z4e49h11id108n843zx9m9il2hd8k8gzgogali0c68li10u1icz0105q4g8g1eg8701zx9m94k1i1z272lai0130t28k6c4ak8gzy0v09m834216p9ki10u1icz8s8521y1272k6c4a521z8s8j33333333j3k9hc2k8gzx2t28k8g0131al40o7843z8s85210gf0p6gg4b421z8s8j33342qg96zx2t24o0n84ogajm25q48gz0g0kb412108co5a40e58n825q48gz131al90632521x8s85q20s3421z272pooooooooooooo48b1i1z272k8gy48s8la430t24ozy0v0id2o48gy02t1ge121z8s8la90go0n8252co5ihg8gzxidi45g9gy08co59n843zy0v09m924d68j33421z8s8521y3he12s0gz8s8j3333333334p1ccfg96zx2t28k8g0oghu1icz0g0kb4216o5ak50p6hh4ak8gz131al9063ka90gfg96o8kb807o48gz272pooooo4b807o48gwidi8kb421z272k8gwv0in25k0jcha5201z4e4a5k0jcha4031121zx131121 | |
0b111110011_110110100_001110010_000110100, #xq1_0g0ocgm362dicz131s4a40361ccs24oz8s8j2l9gm3632521zx1u1q4861q4g8gz0gog74a51odi98343zw10361doc8m96 | |
0b101001011_111100100_001001010_011100100, #xq1_y1gocuroxgy2goz8cgesmg010us6vdcw4m3f6m0gxgosmgz4d2vomsub073trk72vof338nr5ckl1obhtoczy0hv6d114qvor225e1v1t2r4rful1iv8v3r8gwgozy12tnh1307oucmgwv0v0u1t2voesmgw15s4jfm6zy18nthgo0s3f6d1wv0v0fgn8v3e7d1wgk74pudczy0hvcmgg4bv3r88kegvgn8r4ruflg9v2vor21w13z4m8v3d7fq0sonr5s8v3uoo2trk65lg3qhn36z261e7d10g0f7cvm6w4doucd01x137d1zy1136fr3x1y213 | |
0b101001011_111100100_001001010_111100100, #xq1_wgxorucog0mso0gy0cogz0cdv6su0dcui0avt2t1ogrbnpjq8zcih54mql0lvrcv1u0v0vavndv1z6mv0fggg6mvpfv0v0v0g0mmfm9z348q2mla0avt3fon0v0vlvervogz03rf63ngr3nk0lvr4r810ddupc51zy21d731w631y231 | |
0b111001011_111010100_001001000_001010100, #xq1_y3oruc0ogzy0cogkabo1q62z0ogbjf9965h5q072kc4bq8z6mvc62w3rf60342322322c4bq8z01yhor4z0cogy1ogy7g0mpgz3rfhbigg66f3o612ei2mqi1162zx6mvccjls5q07211162zy01wpqug4qb2zy4631 | |
0b101001011_101100100_101001010_101100100, #xq1_y5gocurozwg0ogsomac8b24oz0hladjenblcicvdcy2goczgkbmnutbs3vlg3sfmbo8a3hn3r8gz8nutbt2r4rvl14rvelhin0fulh21z4revlv0v0vv4evelh870uqk75pz2tnvav0n8v3lks3f6mg0f7cudczhervlv0n8v3mg015s8v3rgosroz8ntvav0v0nfq0sfmm0g0p7qn8eicz4revlv0v0t2ucd10317kjg7jdcz2tnvav0v0t2ukv1egv6b80amp7urozhervlv0v0u1tor21gv6ro01uta3icz8ntvav0v0rsl8eai0sva0amp6vdcz4revlv0m9u3ndgevelehvav0m9r8gz2tnvav0dit7fnanonfnao4l14cpudczhervlv0r4ruflgjnbt3srn54ck413z8ntvav0r4tor210u1t2r4tocudcz4ruflfgrkbe88cgf0v0r4tor217uroz2bkfhsjnblcicxgvgm9t0uqkn36z08fjmggo1vcd114qq0suta34f1toczw9mr8825vgn520137etm1fhtk8fbjzgo0vfpsqk759gxg0ovm60fvfpsqpz8q5n42105ckihgo1t2r4t8s0v0mpmgz8fjl4go013gvgm45cotqr130v0djd1z4d2tfnq8i3p7d1xgpmgxv0r7r3zw8fjmggpmf6d10uflfht4o0v0mfm6zx1urox2upl40o7vqo1wv0dudcz4m8v3mgwg2r4tk8f8b24owv0rsroz08nnva0alfgtir130gpvdcwv0mpmgzgkbv3lk1lat3tua25vfkh2s0v0djd1z018nva0amp6v6d11j0f6d1wv0r7r3zw4rvl0lav0r4f1unbrgoxv0mfm6zw2tva0alv0m9f6mg0pvm6wv0dudczwhevl0lav0t2f87udd01xv0rsrozxvvi8a343v3r88cgfmr8g0v0mpmgzw1unbls2s0v0d9akn36wv0v0djd1zw2tv7qo1w1urow261u0v0v0r7r3zw2tfnao4o0s3mgg8a3430v0v0mfm6zw4rvelh210v0tkihfmbogf0v0dudczw8nva0amp6v6mg0pgn36xv0rsrozw4rvl0lav0din0fb5tocxv0mpmgzw2tva0alv0r4n3r8gsfr3wv0djd1zwhevl0lav0u1n43f6m0gxv0r7r3z8cgv7a82bkr7rtk46onbd4o0v0mfm6z0heful1kdidudr225fvpki10v0dudcz08nv7a825f0t2ucmggk75pwv0rsroz1307urox2upd10v0uqpxv0mpmgzwgkbe88o8i3k51ogfnao4o0v0djd1z0g0vmbogc3v3l4037dvcd1wv0r7r3zhlad7fq026cvdcwgosroxv0mfm6zgv6d1x4m8f8bp5p0t2uku0v0dudcz8q5vhqsod11icw4d2upd01gvgrsrozwgfvkh21vdcy2gvb3gfvfkhicz0gkbe88q5vgn520su7rtrk74l1ovm6z0gfmbo88kfhdk412ao9blq6pvcd01z2upnchevelhihg8g0v0r4tor217urozhervlv0u1uro010v0v0u1tomqkn36z8ntvav0u1tomac8bkt2upd01jd1z4revlv0m9u3ndgevelehu7d11hpsmgz2tnvav0dit7fnanonfnaoht49hsjd1zhervlv0r4ruflgjf3trk7ifo3smgz8ntvav0v0u1tor228p7qo23srn59gz4revlv0v0r4t8u2k8v3mg0kbt2uqpz2tnvav0v0t2rhn43073e882bkn36zhervlv0v0dir1tk8e4f1u0velh8gz8ntvav0fgv7a8173rgo0sfqvor21z4revlv0fgv6b8o4l18f6m0gpmgz2tnvav0v0vu5hpmfbjwvv935pzhervlv0v0vv937rtk8f8b2hvdcz8fjdetqmp6vdc1unblsin0fb5sicz09ejnblehendguhn36w26cvm6z04d2tervelhih75py41zy2103apguqpzy7136 | |
0b101001011_111100100_101001010_111100100, #xq1_y48qrkacbqoggggggggggggggggoqbcakrq8zxgo0clr7e7rlrnuntlfuflpj1u5nltnunrlr7e7rlc0ogz463fe268jgc5uu4aa4uu5llueeukk5uu4aa4uu5cgj862ef364zyh23177132 | |
0b111001011_111100100_011001000_001100100, #xq1_xgosuroz2bkvhm52esmgz8q5vhdk8e7d1zx137fr3 | |
0b111001011_111010100_011001000_001010100, #xq1_0goc08cge4ja8gg8aj4egc80cogzxgfir2j1157337511j2rifgzy09ca134ja8gg8aj431ac9z8c6vv6c80115733751108c6vv6c8 | |
0b111001011_111010100_011001000_011010100, #xq1_wgocuroz8q6aalau2s0gzxvujvjvjvdcz4molkblvhf13zw26cvm6zy21 | |
0b111001011_111100100_111001000_001100100, #xq1_oruso0gz0631rq51zorusu2d4z0631 | |
0b111001011_111010100_111001000_001010100, #xq1_4couuv5445vuuoc4zx9l4kjjk4l9zw4c3t8448t3c4 | |
0b110101011_110100100_000101010_000100100, #xq1_y08c6row8c6rowgzgk6jrooop3338o893jdcy0goz0hvha40os66666dc119e882jpm6z15cpr336y3136row15cpccmggow8c6rozw26s66666rooooo2324o0so6qpooq31tp7q324ozwirp333336y126qpw10jqkg8aes54ni6qpz4dpcm66roy1gk63mggg4dpc113y2136z8c7cqpoop333jrlh4ckjw26cr3z0136mg0os66mg0os66d1zy1136y0136 | |
0b111101011_110100100_000101010_010100100, #xq1_08c6roz13u3e88c6roocw8c6roz2bpjoooopm66b51km3mggozwgpmggggpy1gpfpppm6z4dpc11119mmmda826cmg01z8c7cnh136d113w136d1z0136d1 | |
0b111101011_111100100_000101000_001100100, #xq1_or6c8zgmjuj1z1dpc51z3rcogz6m6s62zcdjpb2z031 | |
0b111101011_111010100_000101000_000010100, #xq1_046on2442no64z0gpq4aiia4qpgz11y611 | |
0b110101011_100100100_110101000_000100100, #xq1_0gocy0gy18c6roooooooooocz15svvvfvtosggpf23icy38cbjz4dpn76cm666b5svvrhr3333j338o843zw4ni6qpy0gk7vvvvrhdf3226cr3zy0136y2136y013 | |
0b101101011_110100100_001101000_000100100, #xq1_08ogccgo448um0rf422s86moc4z0gg1v88vs4w1y02uv4kfgo8zw1vuhg3vs4y12uvh88vv0ggz136d1oo173oe6037c1jgsc0631z08ogcc73vs4xgg2uv136moc4zx1306er1c7301360d7301 | |
0b111101011_111100100_001101000_001100100, #xq1_0coooor6c8z3rccc7soorj6kgzy03rpgw3rpgz0or666s733rpc51zw63333rc62 | |
0b111101011_111100100_011101000_000100100, #xq1_wg0msooooooor6c8xcogz0cdjhhtcoggmpoooj33fj01dcogzw311dc62w311cc73333333ec62z0coorj6kggsoojjucccsccc7jm4z3rcoorjhggmph11cccfcgob31zx631111111d631x31 | |
0b110011011_110010100_000011000_010010100, #xq1_xggka2cbv0umo4k8z02tck063f8w1gu6c19pq4z8o7130731y126e072fggzxvjs211is3vgu6o4224l4k8z8oq3gh0e62w10317kgg1e5vgzw103162y61jgcs0e62zyg1 | |
0b110011011_101010100_000011000_101010100, #xq1_xciksks4cck432oom4zxogb6q8wjk8866q8zw3f4bgc8w1dt4ggc8zxo4ntlsgi575d1ddkgzy01y1h0niln5n162z0ciksks46gjhq3qrm51z0ogb6q8012rui66q8z3f4bgc8w6ma8ggc8z0o4ntlsgorkg01ddkgzw1y531w1 | |
0b101011011_110010100_001011010_010010100, #xq1_yoggka2cbv6e0scumo4k8zyc8ki9hqco8si1cg8i3fggy110u64h1p24oggok2i48gzyb2613010317o5oa3073c4u1x2t9o6f07kgbhe3613073c4zyb8k4omu0sc51y44c370e6p8y2103aoo0scg88gz0g84i2koggo42p1h46u01yt1031tc922i48gwg8448gz4c3703163ehbgk70f6o9t2yt4qihcu1e90m3t7d361e6p8zy38oq3ghwgg0oo162yr4c3ghy01307kggzy510316po0hg3c4yt8o7121hic37031zy8130103162yv4c3703162 | |
0b101011011_110010100_001011010_110010100, #xq1_y3g84iccb2zy3124ubtkgwg0sogzy2o4299jio2d51w6ma8ggc8zwgm9q1ce89i66q8xorkg01ddkgzwhttlhy012111162y031w1z69gggghg764ggc8zx3efkkj3td51zy069ggp0gzwgsnviiccbrq8z69ggggo0e62w31zworbq8y0o48o8864ggggc8wogzx695o3719kmm51x1diworb2zy21249pckhkbao0gmm51w31zy3o42ndb2y131zy412433d4 | |
0b101011011_101010100_001011000_001010100, #xq1_04qis8ocqh9ik8y28ki9hqco8siq4zwvdsfa30103162y026130103afsdvzwvm50qt2yc2tq05mvz26130731tc4y84ct13703162z08k4odr6c2s8occeddecco8s2c6rdo4k8zwvp1sbnb1301u684486u1031bnbs1pvz1301w8p6e073c4y04c370e6p8w1031 | |
0b111011011_111010100_001011000_011010100, #xq1_ciksc4ks4ccb2z6mvcjbq8wjb5c07mkgz6nujfrs574c16ma21162zctfpur7ks46gcda8ggc8zcdv6pqb2wpqk60sd51z69576457466q8 | |
0b111011011_110010100_011011000_010010100, #xq1_y1o48o88oosg764ggc8z0gm9q1cj017tu2260sd51z6nbbf3j2mg9vvz348ocnv67rrvvzx17nbbfemvvzy1121rokvvwgzy5jb576ed9zy5pqk433d4zy66ma8ggc8zy6jk8optd4zy3g0m7bvvw31zy1orkltsqvvz0g847drvppmmvvz0pqkkshjgr35vvzw3r5n1diwpfvggo0ec8zy01078565576e2oo833d4zyc1 | |
0b111011011_111010100_011011010_001010100, #xq1_xg84oom4y0ciks4ccb2zw348tmao0gms55c0oue731zwgs8ls55j744erl42s130ec8z69g5rq801211304a46654o833d4zx1w31 | |
0b111011011_111010100_011011000_101010100, #xq1_cikssriy0gxgxogzwjuv111ccbo1f73ufsprb2zcibefnj1y631zy11 | |
0b111011011_111010100_011011010_011010100, #xq1_69qemvseosg7ec8z6svfgairrtf731zw69577r9 | |
0b111011011_111010100_011011000_111010100, #xq1_g84iccb2z124ubtk0gxogz069577rfsprb2zy431 | |
0b111011011_111010100_111011000_001010100, #xq1_0o48oosg7ec8z6utpvvvf731z31f731 | |
0b111011011_111010100_111011000_011010100, #xq1_0o48oosg7ec8z6utpvqtf731z31f731 | |
) | |
spaceship=lambda b,s: any(map(lambda h: not(h&~b&mask or h>>9&~s&mask or b&~h>>18&mask or s&~h>>27&mask),spaceships))''' | |
grey=1 | |
rainbow=0 | |
rules=lap(lambda _: set() if rainbow else 0,range(1<<18)) | |
with open(os.path.join(sys.path[0],('R1-C2-NM-gliders.db.txt','new-gliders.db.txt','May13-gliders.db')[2]),newline='') as db: #https://github.com/jedlimlx/HROT-Glider-DB/blob/master/R1-C2-NM-gliders.db.txt, https://conwaylife.com/forums/viewtopic.php?f=11&t=1074&p=146424#p146424 | |
m=0 | |
for ors in db: | |
s=ors | |
attribution=[] | |
for _ in range(2): | |
attribution.append(s[:s.index(':')]) | |
s=s[s.index(':')+1:] | |
minr=s[:(c:=s.index(':'))] | |
s=s[c+1:] | |
maxr=s[:s.index(':')] | |
sh=s | |
details=[] | |
for _ in range(6): | |
details.append(sh[:sh.index(':')]) | |
sh=sh[sh.index(':')+1:] | |
p,x,y=details[1:4] | |
if '/' in p: p=p[:p.index('/')] | |
p=int(p) | |
x,y=abs(int(x)),abs(int(y));x,y=max(x,y),min(x,y) | |
unsimp=(p,x,y) | |
g=gcd(p,x,y);p//=g;x//=g;y//=g | |
if not speedRequirement or (p,x,y)==speed: | |
minr,maxr=map(lambda r: (lambda b,s: b|s<<9)(*map(lambda t: ORsum(tap(lambda i: (str(i) in t)<<i,range(9))),r.split('/'))),(minr,maxr)) | |
diff=minr^maxr | |
indexes=tilter(lambda i: diff>>i&1,range(18)) | |
for rule in map(ORsum,product(*map(lambda i: (0,1<<i),indexes))): | |
#if printRLEs==2 and (not (rule|minr)&1 and (rule|minr)==~(~0<<18)^bitverse(18,rule|minr)): #do suspicious recording here | |
val={(p,x,y)} if rainbow else 1<<(not speedRequirement and (p,x,y)==speed) #p>2*(x+y) | |
rules[rule|minr]|=val | |
if minr&1 and ~minr&1<<17: | |
rules[bitverse(18,~(~0<<18)^(rule|minr))]|=val | |
if rule|minr==bitverse(18,~(~0<<18)^(rule|minr)): | |
rules[~(~0<<18)^(rule|minr)]|=val | |
if printRLEs and (speedRequirement and (p,x,y)==speed or (m==-1 or diff.bit_count()>=m if printRLEs==2 else not(minr&~particular or particular&~maxr))):# or not (minr^0b1100)&0b1111:#or y==0 and 2*x>p and x!=p and 3*x!=2*p and ~minr&1: | |
if printRLEs==2 and m!=-1: m=max(m,diff.bit_count()) | |
print(', '.join(filter(id,attribution))) | |
if not speedRequirement: print(speedStr(p,x,y)) | |
if g!=1: print('period '+str(p*g)) | |
print(((lambda a,b: '/S'.join(map(lambda a,b: ''.join(map(lambda t: t if t in b else '('+t+')',a)).replace(')(',''),a.split('/S'),b.split('/S'))))(prule(maxr,True),prule(minr,True))+' '+str(1<<diff.bit_count()))+'\nx = '+details[4]+', y = '+details[5]+', rule = '+prule(minr if speedRequirement else particular,True)+'\n'+sh,end='') | |
setBoard(*RLEsize(sh)) | |
printBoard(loadRLE(sh)) | |
particularSpeeds.add(unsimp) | |
count+=1 | |
input() | |
if printRLEs: print(speedStr(*speed) if speed else prule(particular),count,', '.join(starmap(lambda p,x,y: '('+str(x)+','+str(y)+')c/'+str(p) if y else (x!=1)*str(x)+'c/'+str(p),sorted(particularSpeeds,key=lambda t: (Fraction(t[2],t[1]),Fraction(t[0],t[1]+t[2]),gcd(*t))))));exit() | |
spaceship=lambda b,s: rules[b|s<<9] or b==~(~0<<9)^bitverse(9,s) and ~b&1 and rules[~(~0<<18)^(b|s<<9)] | |
disproven=lambda b,s,sub=False: not(b&1 and s&1<<8) and ((not(~b&0b1110 or s&0b11100000) or not(~b&0b111110000 or s&0b11111) or not(~b&0b011110000 or s&0b11110) or not((b^0b0010)&0b1110 or (s^0b1100000)&0b11100000) or ~b&1<<1 and s&1<<7 or b&1<<1 and ~b&1<<2 and not ~s&0b11<<6 or (((~b&0b10 or ~b&0b1100 and not s&0b1111 or not b&0b1100 and not s&1 or not s&0b11111) and (s&1<<7 or not ~b&0b111110000 or not ~b&0b111100000 and s&0b1100000 or b&1<<8 and not ~s&0b1100000) or s&1<<6 and not b&0b110 or not ~s&0b11<<6 and not b&0b100 or not ~b&0b1110 and not s&0b111<<5)) if b&1 else not b&0b1110 or not ~s&0b1111 or b&0b10 or not(~b&0b1100) and s&1 or not (s^0b11110)&0b11111 or ((b&0b10 or not ~b&0b1100 and s&1 or not ~s&0b1111110 or not ~b&0b11000 and not ~s&0b111110 or not ~b&0b111000 and not ~s&0b11110 or ~b&0b100 and not ~s&0b11111100 or not ~s&0b11111 or b&0b11<<2 and not ~s&0b1111)) or False and not ~b&0b11100 and s&0b10)\ | |
or (speedRequirement and 2*(speed[1]+speed[2])>speed[0] and (not(~b&0b110 and bitverse(9,s)&0b110) and not(~s&0b110000 and bitverse(9,b)&0b110000) or 4*speed[1]+3*speed[2]>2*speed[0] and (bool(~b&0b110)+bool(bitverse(9,s)&0b110)+(~s&0b110000)+(bitverse(9,b)&0b110000)<4) if b&1 else not(b&0b110) and not(s&0b110000))))\ | |
or not sub and ((b&1 or ~s&1<<8) and disproven(*map(lambda n: bitverse(9,~(~0<<9)^n),(s,b)),True) or b==~(~0<<9)^bitverse(9,s) and disproven(~(~0<<9)^b,~(~0<<9)^s,True)) | |
#print(sum(starmap(compose(disproven,bool),product(range(1<<9),repeat=2))));exit() | |
'''unknown=[] | |
for b,s in product(range(1<<9),repeat=2): | |
if not(spaceship(b,s) or disproven(b,s) or b&1):# and b==~(~0<<9)^bitverse(9,s): | |
unknown.append((b,s)) | |
for r in range(8): print('B'+'/S'.join(map(lambda n: ''.join(map(lambda i: str(i)*(n>>i&1),range(9))),__import__('random').choice(unknown)))) | |
exit()''' | |
#print('\n|-\n'.join(map(lambda y: '|'+'||'.join(map(lambda x: 'style="background:#'+('c0c0c0','80ff80','ffa0a0')[bool(disproven(*(c:=(c:=(x^x>>1)<<1|(y^y>>1)<<5,~(~0<<9)^bitverse(9,c)))))<<1|bool(spaceship(*c))]+';"|{{cata|census/'+'|'.join(starmap(lambda b,s: b+s.join(map(lambda n: ''.join(map(lambda i: str(i)*(n>>i&1),range(9))),c)),(('b','s'),('B','/S'))))+'}}',(3,7,8,12))),range(16)))) | |
#print(rle(sorted(tarmap(lambda b,s: (lambda b,s: 3*(0xff,) if b==0b1000 and s==0b1100 else (0xff,spaceship(b,s) and 0xff,0) if disproven(b,s) else (0,0xff,0) if spaceship(b,s) else 3*(b&1 and ~s&1<<8 and 0x33,))(*((bitverse(9,mask^s),bitverse(9,mask^b)) if b&1 and s&1<<8 else (b,s))), starmap(lambda x,y: tap(lambda n: n or n^n>>1,(bitverse(9,x),y)) if not grey else tap(lambda n: bitverse(9,n^n>>1),(x,y)) if x<1<<8 else (bitverse(9,x^x>>1),y^y>>1) if y<1<<8 else ((x&~(1<<8))^(x&~(1<<8))<<1|1,y^y>>1),product(range(1<<9),repeat=2)) if True else chain(product(map(lambda n: bitverse(9,n^n>>1),range(1<<8)),map(lambda n: bitverse(9,n^n>>1),range(1<<9))),product(map(lambda n: bitverse(9,n^n>>1),range(1<<8,1<<9)),map(lambda n: n^n>>1,range(1<<9))))))));exit() | |
if rainbow: speeds=sorted(reduce(set.__or__,map(saph(lambda s: Fraction(s[1]+s[2],s[0])),rules)))#;print(len(reduce(set.__or__,rules)),len(speeds));exit() | |
img=Image.frombytes('RGB',2*(1<<9,),bytes(charmap(lambda b,s: (lambda b,s: 3*(0xff,) if False and b==0b1000 and s==0b1100 else (3*(0x33,) if disproven(b,s) else tap(compose((32.).__mul__,int,minh(255)),reduce(taph(__add__),starmap(lambda p,x,y: triangleWave((x+y)/(p*speeds[-1]) if True else speeds.index(Fraction(x+y,p))/len(speeds)),rules[b|s<<9]))) if rules[b|s<<9] else 3*(0,)) if rainbow else (0xff,spaceship(b,s) and 0xff,0) if disproven(b,s) else (0,spaceship(b,s)&1 and 0xff,spaceship(b,s)&2 and 0xff) if spaceship(b,s) else 3*((False and b&1) and ~s&1<<8 and 0x33,))(*((bitverse(9,mask^s),bitverse(9,mask^b)) if b&1 and s&1<<8 else (b,s))), starmap(lambda x,y: tap(lambda n: n or n^n>>1,(bitverse(9,x),y)) if not grey else tap(lambda n: bitverse(9,n^n>>1),(x,y)) if x<1<<8 else (bitverse(9,x^x>>1),y^y>>1) if y<1<<8 else ((x&~(1<<8))^(x&~(1<<8))<<1|1,y^y>>1),product(range(1<<9),repeat=2)) if True else chain(product(map(lambda n: bitverse(9,n^n>>1),range(1<<8)),map(lambda n: bitverse(9,n^n>>1),range(1<<9))),product(map(lambda n: bitverse(9,n^n>>1),range(1<<8,1<<9)),map(lambda n: n^n>>1,range(1<<9))))))).transpose(5) | |
else: | |
inputcode=input('apgcode ') | |
if (suspicious:=inputcode[:3]=='x ='): | |
inRLE=[inputcode] | |
while not inRLE or '!' not in inRLE[-1]: inRLE.append(input()) | |
state=loadRLE('\n'.join(inRLE)) | |
objectType=0 | |
period=int(input('what is the period, perchance ')) | |
shifts=(0,0) | |
for i in range(period+1): | |
state=iterateCellular(state,2-objectType) | |
if objectType: | |
shifts=tap(int.__add__,shifts,(shiftX,shiftY)) | |
else: | |
(period,state)=analyse(inputcode,-1) | |
states=tuple(expumulate(iterateCellular,period-1)(state)) | |
subpixels=(period if objectType else 1) #I was going to do lcm(lcm(period,shifts[0]),lcm(period,shifts[1])) but then remembered they are factors | |
upscale=8**(not objectType) | |
overlays=tuple(tarmap(lambda o,s: (lambda i: i>=0 and s>>i&1)(((y+o*shifts[1]*subpixels//period)//subpixels*cellWidth*WIDTH if OT or byteINT else 3*WIDTH*(y*3+1)+1)+(x+o*shifts[0]*subpixels//period)//subpixels*cellWidth),enumerate(states)) for y in range(subpixels*HEIGHT) for x in range(subpixels*WIDTH)) | |
print(stators:=sum(map(all,overlays)),'stators',rotors:=sum(map(any,overlays))-stators,'rotors',strict:=stators+rotors-sum(map(lambda c: any(c) and any(map(lambda f: all(map(lambda i: c[i*f:(i+1)*f]==c[(i+1)*f:(i+2)*f],range(period//f-1))),factorise(period)[:-1])),overlays)),'strict') | |
cells=tuple(tap(lambda c: min(int(rms(c)*255),255),zip(*starmap(lambda o,s: triangleWave(o,period) if s else (0,0,0),enumerate(overlays[x+y*subpixels*WIDTH])))) for y in range(subpixels*HEIGHT) for x in range(subpixels*WIDTH)) | |
#cells=tuple(tap(lambda c: min(int(rms(c)*255),255),zip(*starmap(lambda o,s: triangleWave(o,period) if (lambda n,i: i>=0 and n>>i&1)(s,((y+o*shifts[1]*subpixels//period)//subpixels*cellWidth*WIDTH if OT or byteINT else 3*WIDTH*(y*3+1)+1)+(x+o*shifts[0]*subpixels//period)//subpixels*cellWidth) else (0,0,0),enumerate(states)))) for y in range(subpixels*HEIGHT) for x in range(subpixels*WIDTH)) | |
#from colorsys import hsv_to_rgb | |
#img=Image.frombytes('RGB',(100,360),bytes(int(0.5+255*u) for hue in range(360) for sat in range(100) for u in hsv_to_rgb(hue/360, sat/100, 1))) #demo from https://stackoverflow.com/a/48280414 | |
img=Image.frombytes('RGB',(subpixels*WIDTH,subpixels*HEIGHT),bytes(chain.from_iterable(cells))).resize((upscale*subpixels*WIDTH,upscale*subpixels*HEIGHT),resample=Image.BOX) | |
img.save((lambda s: 'xp'+str(period)+'_suspicious_'+rulestring if suspicious else s[:s.index('_')]+'_toolong_'+rulestring if len(s)>256-4 else s)(inputcode)+'.png') | |
img.show() | |
elif mode==2: | |
try: | |
from eightfold_reducer import reducer | |
except: | |
raise(ImportError("no eightfold reducer (get it at https://github.com/DroneBetter/ChessPieceVision/blob/main/eightfold%20reducer.py and put it in my folder :-)")) | |
setBoard(*((int(input("board width ")),)*2)) | |
bounded=(not (edges or corners or nearCorners) or input("include patterns that exceed the bounds? "+"(rule is gutter-preserving) "*gutterPreservation).lower() in {'y','yes'}) | |
r=reducer(boardWidth,True,True,cellWidth,cellHeight,OT,byteINT) | |
#print(len(set(r[:]))) | |
sliceNum=int(input("there are "+str(len(r))+" states, how many slices would you like? ")) | |
slicer=(lambda n: (lambda i,f: (f-i,slice(i,f,1)))(*map(lambda i: len(r)*i//sliceNum,(n,n+1)))) | |
(l,sliceAttempted)=slicer(int(sliceNum!=1 and input("which would you like to search? "))) | |
n=1<<(14+2*OT)#min(l>>10,4096) | |
finals=set() | |
t=time() | |
for i,s in enumerate(r[sliceAttempted]): | |
if not i%n and i: | |
print((lambda t: str(i)+'/'+str(l)+' ('+str(100*i//l)+'%) in '+str(int(t*1000)/1000)+'s, '+str(int(n//t))+' soups/s, '+str(int((len(r)-i)*t)//n)+'s remaining')(time()-t)) | |
t=time() | |
past=[] | |
state=s | |
#print('it begins') | |
#printBoard(state) | |
while state not in past: | |
past.append(state) | |
state=iterateCellular(state) | |
#printBoard(state) | |
finals.add((lambda p: (p,min(map(r.symmetry,past[-p:]))))(len(past)-past.index(state))) | |
print(len(finals)) | |
m=max(p for p,s in finals) | |
for p,s in finals: | |
if p>2 or m==2: | |
printBoard(s) | |
print(p) | |
elif mode: | |
import os,csv | |
interface=(input('interface? ')=='y') | |
name='' | |
while not name: name=input("name ") | |
if name[-7:]=='_sorted': name='sorted_'+name[:-7] #in case I forget which way around it is (surprisingly often) | |
if interface: | |
def reversedLines(file,blocksize=4096): #from https://stackoverflow.com/a/10933932 | |
part='' | |
file.seek(0,os.SEEK_END) | |
here=file.tell() | |
while 0<here: | |
delta=min(blocksize,here) | |
here-=delta | |
file.seek(here,os.SEEK_SET) | |
block=file.read(delta) | |
for c in reversed(block): | |
if c=='\n' and part: | |
yield(part[::-1]) | |
part='' | |
else: part+=c | |
if part: yield(part[::-1]) | |
with open(os.path.join(sys.path[0],name+".csv"),newline='') as census: | |
revsus=reversedLines(census) | |
oscillators=[] | |
while True: | |
oscillators.append((next(revsus).strip('\n'))[1:-2].split('","')) | |
apgcode=oscillators[-1][0] | |
wibble=True | |
if wibble: | |
p=int(apgcode[2:apgcode.index('_')]) | |
printBoard(tuple(redumulate(lambda s,_: iterateCellular(s),range(p-1),reduce(lambda s,_: iterateCellular(s,2),range(p),loadapg(apgcode)))),phases=True) | |
else: | |
printBoard(loadapg(apgcode)) | |
print(*oscillators[-1][:2]) | |
analyse(apgcode,(0,1,2,3,4),True) | |
input() | |
else: | |
volatilityThreshold=0.8 | |
cond=(lambda v: not v if metric==4 else v>(28 if name=='xp5' else 20) if metric==3 else v==False if metric==2 else v[0]<volatilityThreshold) | |
#analyse("xp30_w33z8kqrqk8zzzx33")#("xp8_gk2gb3z11") | |
metric=0 #0: volatility, 1: heat, 2: polyomino?, 3: minpop, 4: gutter-preserving? | |
with open(os.path.join(sys.path[0],name+".csv"),newline='') as census: | |
next(census) | |
nice=[(lambda p,o: (p[1:-1],int(o[1:-2])))(*c.split(',')) for c in census] | |
metrics=[analyse(n[0],(metric,)) for n in nice] | |
nicests=sorted(zip(metrics,nice)) | |
with open(os.path.join(sys.path[0],"sorted_"+name+".csv"),'w',newline='') as census: | |
wr=csv.writer(census,quoting=csv.QUOTE_ALL) | |
wr.writerows((*n,v) for v,n in nicests) | |
for v,n in nicests[::(-1)**(metric!=3)]: | |
if v==None or cond(v): | |
break | |
printBoard(loadapg(n[0]),symbol='') | |
print(*n,v) | |
suspicious=1 #very suspicious | |
if suspicious: | |
print('All known {{period|'+str(period)+'}} oscillators with [[volatility]] of at least '+str(volatilityThreshold)+'.\n{|class="wikitable sortable" style="margin-left:auto; margin-right:auto; clear:both; text-align:center"\n! Rank !! Name !! Image !! Rotor Size !! Volatility'+' !! Strict volatility'*(len(factorise(period))>2)) #very suspicious | |
round=(lambda n,d=3: (lambda n: n+'0'*(d+2-len(n)))(str(int(n*10**d)/10**d))) | |
for i,(v,n) in enumerate(nicests[::-1],start=1): #start=1 is a constant source of pain to me however we wouldn't want to upset the ordinal pedants | |
if v==None or cond(v): | |
break | |
if suspicious: print('|-\n|'+str(i)+'||{{LinkCatagolue|code='+n[0]+'|style=raw|patternname=unnamed}}||[[File:'+n[0]+'.png|96px]]||96||'+round(v[0])+'||'+round(v[1])) | |
else: print(RLE(loadapg(n[0]))[:-1]+'3$')#print(*n,v) | |
if suspicious: print('|}') | |
else: | |
testGlider=True | |
#state=(lambda r: loadRLE(r+'\n'+input()) if r else loadRLE("$$b3o$bobo$2b2o3b2o$7b2o2$b2o$obo$bo!" if rulestring=="b3ai4s23" else "$$3o$2bo$bo!") if testGlider else int.from_bytes(os.urandom(STATE_BYTE_LENGTH),"little") & MASK_1)(input('RLE ')) | |
inRLE=[] | |
while not inRLE or '!' not in inRLE[-1]: inRLE.append(input()) | |
state=loadRLE('\n'.join(inRLE)) | |
while True: | |
state=iterateCellular(state,manifold==(0,0) and False) | |
if yuv4mpeg: | |
#output a (gzip-compressed!) YUV4MPEG frame | |
sys.stdout.buffer.write(deflate_verbatim(b"FRAME\n")) | |
sys.stdout.buffer.write(MAGIC_HUFFMAN_TREE) | |
sys.stdout.buffer.write((state>>BIAS-3).to_bytes(WIDTH*HEIGHT>>1,"little")) | |
sys.stdout.buffer.write(b"\x04") | |
else: | |
print(RLE(state)) | |
printBoard(state) | |
sleep(1/FPS) | |
#print(state.bit_count()) | |
if state.bit_count()==290: | |
print(RLE(state));exit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Made for use in my tablebase program's oscillator search/visualisation mode (which currently works by only storing states as lists of booleans and storing a list of each cell's neighbourhood to account for manifolds instead of computing on-the-fly), but can be used by others also if you'd like. gzip_swar_life has toroidal vertical scrolling and horizontal skewed scrolling (from the fact that bitwise operators scroll around, so each cell on the right edge perceives the one on the left edge a row down as being orthogonally adjacent to it rightwards), this makes it a correct torus in both axes by immersing within a mask scrolled left and right as well as up and down. But tablebase vision supports topological manifolds with axes like Möbius strips (ie. Klein bottles where one axis is toroidal and the other Möbius, and real projective planes where both are Möbius). To achieve this in a bitwise implementation, you must reverse the order of bits. You can reverse a 2**n-bit number in 5*n operations, and for non-power-of-2-bit widths, you can generate the functions for the first power of 2 after the width, and bitshift left by half the difference between them at the beginning, and right at the end, however it can be optimised further by bitwise arithmetic. It also enacts these operations only once on the scrolling bitmasks in each axis, by copying the reversal AND-masks to both sides.
I will make a bitwise simulator for isotropic non-totalistic cellular automata, eventually.
Edit: I have finished that (in this program for convenience), it works by having each cell in the centre of a 3*3 square of bits instead of the rightmost cell of four consecutive ones, and bitwise-ORing it with displaced versions of itself (instead of summing) such that the bits around each cell are its neighbourhood, then bitwise-XORing with the bitwise NOT of the mask for each MAP transition and folding by bitwise ANDs up and down as well as left and right, it will take longer and I don't know how I'd make it work with YUV4MPEG (as the original one was intended to do efficiently (being that 4 bits is half a byte, as well as the number capable of storing nine possibilities (neighbourhood sum range 0 to 8 inclusive))), but it should be many times faster than my original boolean list implementation in any case.
Edit once more: Now featuring INT simulation in eight cells per byte (see explanation here), RLE header loading and preliminary testing mode (enabled by default in non-video mode) for simulation on an infinite plane (extremely suspiciously, by exporting it to an RLE, changing the board size to have a one-cell margin and reimporting it), will be used in implementing an idea of mine eventually
Edit again: Can now import and analyse apgcodes, currently only sorts by volatility (not intended to be fast but to be able to peruse Catagolue on my behalf so I can spend less of my life doing so), turn off demoMode and put it in the same folder as a census backup containing only oscillators of the specified period (explained in this wiki article) named
census.csv
and then wait (currently you can download all of a period but trying all fromb3s23/all-soups
(as you may be inclined to do if you become mad with power) seems to make the file cut off midway through), it will show you some but also createssorted_census.csv
(in ascending order of volatility for more comedic effect)