new-glider.py

For scripts to aid with computation or simulation in cellular automata.
Post Reply
User avatar
May13
Posts: 426
Joined: March 11th, 2021, 8:33 am

new-glider.py

Post by May13 » July 24th, 2022, 11:19 am

This is a script for reading databases like new-glider.db.
Script works like original glider.c, but it can read oscillators.db and databases for rules with hexagonal and (maybe) von Neumann neighborhood.

Code: Select all

from math import gcd
#Options
map_count_rules=True
file="new-gliders.db" #Name of database
wid=72 #Width of RLE (default: 72)
old_speed=False #if True, use format "2c/5 slope 2"; if False, use format "(2,1)c/5"
#
au="" #part of command (author)
map_char="0123456789abcdefghijklmnopqrstuvwxyz"
com_p="nuvpis/*"
disc_0=":UNKNOWN:"
files={"new-gliders.db": ("OT","glider",True), "oscillators.db": ("OT","oscillator",True), "hex-gliders.db": ("Hex","glider",True), "hex-oscillators.db": ("Hex","oscillator",True), "vn-gliders.db": ("von_Neumann","glider",True), "vn-oscillators.db": ("von_Neumann","oscillator",True)}
mode=files[file][0] #OT #Hex #von_Neumann
neighbors={"OT": 8, "Hex": 6, "von_Neumann": 4}
postfix={"OT": "", "Hex": "H", "von_Neumann": "V"}
type=files[file][1] #glider #oscillator
pat_type={"glider": ("Glider", "glider", "gliders"), "oscillator": ("Oscillator", "oscillator", "oscillators")}
auth_splitters=[[","],[";"],[" based"," by "],[" improved"," by "],[" reduced"," by "],[" and "],[" by D8_2 reduction of an existing ship"],[" by D8_2 reduction of "]]
auth_date=[[" before "],[" early ","s"],[" pre-"]]
hex_glider_impossible=[["2","012","2456","0123456","No gliders can exist: with B2/S012H, patterns can not shrink."],["23","01","23456","0123456","No gliders can exist: with B23/S01H, patterns can not shrink."],["234","0","23456","023456","No gliders can exist: with B234/S0H, patterns can not shrink."],["23","0234","2356","023456","No gliders can exist: with B23/S0234H, patterns can not permanently shrink."],["2","12345","23456","123456","No gliders can exist: with S12345H, connected patterns can not shrink"]]
hex_glider_impossible+=[["0123456","","0123456","",""],["012456","4","0123456","4",""],["012","5","0123456","45",""],["013456","4","013456","4",""],["01356","34","013456","34",""],["013","5","013456","345",""],["01","5","01456","2345",""],["016","1234","0156","1234",""],["01","15","0156","12345",""],["0","5","023456","012345",""]]
hex_glider_impossible+=[["012","","0123456","0123","No gliders can exist: with B012H and without S456H, patterns can not escape bounding orthogonal hexagon"]]
hex_glider_impossible+=[["0","","01","01","No gliders can exist: with B0H and without B23456/S23456H, patterns can not escape bounding orthogonal hexagon"]]
hex_glider_impossible+=[["01234","01234","0123456","012345","No gliders can exist: with B01234/S01234H and without S6H, patterns can not escape bounding orthogonal hexagon"]]
if mode == "Hex": glider_impossible=hex_glider_impossible
else: glider_impossible = []
g=gt=""
def load_db():
	global g, gt
	if files[file][2]==True:
		f=open(file)
		g=f.read()
		f.close()
	gt=g.split("\n")
	g=[i.split(":") for i in (gt[:-1] if gt[-1]=="" else gt)]
load_db()
def N1(): return neighbors[mode]+1
def pt(x): return pat_type[type][x]
int_to_trans=lambda x: "".join(str(i) for i in range(N1()) if x//(2**i)%2==1)
trans_to_int=lambda x: sum(2**i for i in range(N1()) if str(i) in x)
inv_trans=lambda x: "".join(str(i) for i in range(N1()) if not str(N1()-1-i) in x)
def authors(info):
	i=info
	for j in auth_splitters+auth_date:
		if len(j)==1:
			i=i.replace(j[0],":")
		elif len(j)==2:
			while j[0] in i:
				sliceA=i.find(j[0])
				sliceB=i.find(j[1],sliceA+len(j[0]))
				if sliceB<0: break
				i=i[:sliceA]+":"+i[sliceB+len(j[1]):]
	i=i.split(":")
	j=0
	while j < len(i):
		if i[j] in [""," "]:
			i.pop(j)
			continue
		if i[j][0]==" ": i[j]=i[j][1:]
		if i[j][-1]==" ": i[j]=i[j][:-1]
		if i[j].isnumeric() or (i[j][:-1].isnumeric() and i[j][-1]=="?"):
			i.pop(j)
			continue
		j+=1
	if i==[]: i=[disc_0]
	return i
def exclude(command,dx1,dy1,p1,p,info=""):
	if not au=="":
		if not au in authors(info): return True
	cond=False
	if "c" in command:
		vel=command
		for k in com_p:
			vel=vel.replace(k,"")
		vel=vel.split("c")
		if type=="oscillator":
			if vel[1]=="":
				if p==1: cond=True
			elif p==int(vel[1]): cond=True
		else:
			tdx=tdy=tp=0
			if vel[0]=="": tdx=1
			elif "," in vel[0]: tdx,tdy=[int(k) for k in vel[0].split(",")]
			else: tdx=int(vel[0])
			if "d" in vel[1]: tdy=tdx
			elif "k" in vel[1]: tdy=-1
			elif "o" in vel[1]: tdy=0
			elif not "," in vel[0]: tdy=-2
			tp=vel[1]
			for k in "odk": tp=tp.replace(k,"")
			if tp=="": tp=1
			else: tp=int(tp)
			if tdy==-1:
				if dy1>0 and dy1<dx1 and dx1*tp==tdx*p1: cond=True
			elif tdy==-2:
				if dx1*tp==tdx*p1: cond=True
			else:
				if dx1*tp==tdx*p1 and dy1*tp==tdy*p1: cond=True
	else:
		if "o" in command and dy1==0: cond=True
		elif "d" in command and dy1==dx1: cond=True
		elif "k" in command and dx1>dy1>0: cond=True
		elif not ("o" in command or "d" in command or "k" in command): cond=True
	return not cond
def tr4(width,index):
	if (index//width)%4 in [0,3]: return 0
	return 1
def detect_shift(d1,d2):
	if mode=="Hex":
		dx=int(d1)
		dy=int(d2)
		if dx<0 and dy>0:
			if dx+dy>0: dy+=dx
			else: dx+=dy
		elif dx>0 and dy<0:
			if dx+dy>0: dx+=dy
			else: dy+=dx
	else:
		dx=int(d1)
		dy=int(d2)
	return abs(dx), abs(dy)
def detect_speed(dx,dy,p):
	if "/" in p:
		mod=int(p.split("/")[1])
		p0=int(p[:-2])
	else:
		mod=1
		p0=int(p)
	dx0,dy0=max(dx,dy),min(dx,dy)
	gcd3=gcd(p0,gcd(dx0,dy0))
	p1=p0//gcd3
	dx1=dx0//gcd3
	dy1=dy0//gcd3
	return dx1,dy1,p1,p0,mod,gcd3
def get_rule_sets(min1,min2,max1,max2):
	minset1=set(min1[1:])
	maxset1=set(max1[1:])
	if mode in ["Hex","von_Neumann"]:
		minset2=set(min2[1:-1])
		maxset2=set(max2[1:-1])
	else:
		minset2=set(min2[1:])
		maxset2=set(max2[1:])
	return minset1,minset2,maxset1,maxset2
def print_rule_simple(amin1,amin2,amax1,amax2,agens):
	anumstr="".join(str(i) for i in range(N1()))
	print("#C B"+anumstr+" S"+anumstr+(" G"+str(agens) if agens>2 else "")+(" "+postfix[mode] if len(postfix[mode])>0 else ""))
	bs=""
	ss=""
	minset1,minset2,maxset1,maxset2=get_rule_sets(amin1,amin2,amax1,amax2)
	for i1 in range(N1()):
		if str(i1) not in maxset1: bs+="-"
		elif str(i1) in minset1: bs+="X"
		else: bs+=" "
		if str(i1) not in maxset2: ss+="-"
		elif str(i1) in minset2: ss+="X"
		else: ss+=" "
	print("#C  "+bs+"  "+ss+"\n#C")
def print_RLE(ax,ay,arul,RLE):
	print("x = "+ax+", y = "+ay+", rule = "+arul)
	t1=""
	t0=""
	k=0
	for j in RLE:
		if j in "bo$":
			if len(t0)+len(t1)>=wid:
				print(t1)
				t1=t0+j
				k=0
			else:
				t1+=t0+j
			t0=""
		else: t0+=j
		k+=1
		if j=="!":
			if len(t1)==wid: print(t1+"\n!")
			else: print(t1+"!")
def glider(n,rul="",com=":"):
	gi=g[n-1]
	if rul=="": rul=gi[2]
	x1,x2=rul.split("/")
	min1,min2=gi[2].split("/")
	max1,max2=gi[3].split("/")
	if (set(min1) <= set(x1) <= set(max1)) and (set(min2) <= set(x2) <= set(max2)):
		if True:
			dx, dy=detect_shift(gi[5],gi[6])
			dx1,dy1,p1,p,mod,gcd3=detect_speed(dx,dy,gi[4])
			if com!=":" and exclude(com,dx1,dy1,p1,p,g[i][1]): return False
			if dx1==1: dx2=""
			else: dx2=dx1
			if dx==dy and dx1==0:
				if p==1: speed=", still life"
				else: speed=f", period {p}"+(f" (mod {p//mod})" if mod>1 else "")
			elif dy1==0: speed=f", {dx2}c/{p1} orthogonal"
			elif dy==dx: speed=f", {dx2}c/{p1} diagonal"
			else:
				if old_speed:
					sg=gcd(dx1,p1)
					if dx1==sg: dx3=""
					else: dx3=dx1//sg
					if p1==sg: p3=""
					else: p3=f"/{p1//sg}"
					sg1=gcd(dx1,dy1)
					if dy1==sg1: dy4=""
					else: dy4="/{dy1//sg1}"
					dx4=dx1//sg1
					speed=f", {dx3}c{p3} slope {dx4}{dy4}"
					if sg>1: speed+=" (period "+str(p)+")"
				else: speed=f", ({dx1},{dy1})c/{p1}"
			if not (dx==dy and dx1==0):
				if mod==2: speed+=" (period "+str(p)+"/2)"
				elif gcd3>1: speed+=" (period "+str(p)+")"
			if gi[0]=="": print("#C "+pat_type[type][0]+" "+str(n)+speed)
			else: print("#C The "+gi[0]+" ("+pat_type[type][1]+" "+str(n)+")"+speed)
			if gi[1]!="": print("#C Discovered by "+gi[1]+"\n#C")
			else: print("#C")
			print_rule_simple(min1,min2,max1,max2,2)
			print_RLE(gi[7],gi[8],rul,gi[9])
			return True
	return False
def create_map(m1,d1,m2,d2,command=""):
	mapset=False
	if "v" in command or "u" in command: mapset=True
	if mapset: map=[set() for i in range(4**(neighbors[mode]+1))]
	else: map=[0]*(4**(neighbors[mode]+1))
	for i in g:
		dx,dy=detect_shift(i[5],i[6])
		dx1,dy1,p1,p,mod,gcd3=detect_speed(dx,dy,i[4])
		if exclude(command,dx1,dy1,p1,p,i[1]): continue
		min1,min2=i[2].split("/")
		max1,max2=i[3].split("/")
		gminset1,gminset2,gmaxset1,gmaxset2=get_rule_sets(min1,min2,max1,max2)
		add0=0
		addb=[]
		for j in range(N1()):
			if str(j) in gminset1:
				add0+=2**j
			if str(j) in gminset2:
				add0+=2**(j+N1())
		for j in range(2**len(gmaxset1-gminset1)):
			add1=add0
			for k in range(len(gmaxset1-gminset1)):
				if j//(2**(len(gmaxset1-gminset1)-k-1))%2==1: add1+=2**(int(list(gmaxset1-gminset1)[k]))
			addb+=[add1]
		for a in addb:
			for j in range(2**len(gmaxset2-gminset2)):
				ak=a
				for k in range(len(gmaxset2-gminset2)):
					if j//(2**(len(gmaxset2-gminset2)-k-1))%2==1: ak+=2**(int(list(gmaxset2-gminset2)[k])+N1())
				if ak%2==1:
					b0_a=trans_to_int(inv_trans(int_to_trans(ak%(2**N1()))))*(2**N1())+trans_to_int(inv_trans(int_to_trans(ak//(2**N1()))))
				for add1 in [ak]+([b0_a] if ak%2==1 else []):
					if mapset:
						if "u" in command: map[add1].add((max(dx,dy),min(dx,dy),p))
						else: map[add1].add((dx1,dy1,p1))
					elif "p" in command:
						if map[add1]==0: map[add1]=p
						else: map[add1]=max(map[add1],p)
					elif "i" in command:
						if map[add1]==0: map[add1]=p1
						else: map[add1]=max(map[add1],p1)
					elif "s" in command:
						if map[add1]==0: map[add1]=max(int(i[7]),int(i[8]))
						else: map[add1]=min(map[add1],max(int(i[7]),int(i[8])))
					else: map[add1]+=1
	colsM=sum(2**int(i) for i in m1)
	rowsM=sum(2**int(i) for i in m2)
	cols=[colsM+sum(2**int(d1[j])*tr4(2**(len(d1)-j-1),i) for j in range(len(d1))) for i in range(2**len(d1))]
	rows=[rowsM+sum(2**int(d2[j])*tr4(2**(len(d2)-j-1),i) for j in range(len(d2))) for i in range(2**len(d2))]
	text=" "*(len(m2)+len(d2)+3)+" B"*2**len(d1)+"\n"
	for i in m1:
		text+=" "*(len(m2)+len(d2)+3)+(" "+i)*2**len(d1)+"\n"
	for i in d1:
		text+=" "*(len(m2)+len(d2)+4)
		for j in cols:
			if j//(2**int(i))%2==1: text+=i+" "
			else: text+="  "
		text+="\n"
	text+=" "*(len(m2)+len(d2)+3)+"-"*2**len(d1)*2+"\n"
	q=[]
	co1=0
	co2=0
	for i in rows:
		text+="S"+m2
		for j in d2:
			if i//(2**int(j))%2==1: text+=j
			else: text+=" "
		text+=" :"
		for j in cols:
			non_im=True
			for k in glider_impossible:
				if (set(k[0]) <= set(int_to_trans(j)) <= set(k[2])) and (set(k[1]) <= set(int_to_trans(i)) <= set(k[3])):
					text+="  "
					non_im=False
			if non_im and j%2==1:
				for k0 in glider_impossible:
					if (set(k0[0]) <= set(inv_trans(int_to_trans(i))) <= set(k0[2])) and (set(k0[1]) <= set(inv_trans(int_to_trans(j))) <= set(k0[3])):
						text+="  "
						non_im=False
			if non_im:
				co1+=1
				t=map[i*2**N1()+j]
				if mapset: t=len(t)
				ti=t
				if t>35: t="X"
				elif t==0: t="."
				else: t=map_char[t]
				if not t==".": co2+=1
				text+=" "+t
			else:
				t=map[i*2**N1()+j]
				if mapset:
					if len(t)>0:
						print("Error!")
						print(t)
				else:
					if t>0:
						print("Error!")
						print(t)
		text+="\n"
	print(text)
	if map_count_rules: print(f"\n{co2}/{co1}")
def create_list(command=""):
	print(f"Totalistic rules for which {command}{'' if command=='' else ' '}{pt(2)}{' discovered by '+au if not au=='' else ''} are known:\n\n    B{''.join(str(i) for i in range(N1()))} S{''.join(str(i) for i in range(N1()))} {postfix[mode]}")
	map=[False]*(4**(neighbors[mode]+1))
	for i in g:
		dx,dy=detect_shift(i[5],i[6])
		dx1,dy1,p1,p,mod,gcd3=detect_speed(dx,dy,i[4])
		if exclude(command,dx1,dy1,p1,p,i[1]): continue
		min1,min2=i[2].split("/")
		max1,max2=i[3].split("/")
		gminset1,gminset2,gmaxset1,gmaxset2=get_rule_sets(min1,min2,max1,max2)
		add0=0
		addb=[]
		for j in range(N1()):
			if str(j) in gminset1:
				add0+=2**j
			if str(j) in gminset2:
				add0+=2**(j+N1())
		for j in range(2**len(gmaxset1-gminset1)):
			add1=add0
			for k in range(len(gmaxset1-gminset1)):
				if j//(2**(len(gmaxset1-gminset1)-k-1))%2==1: add1+=2**(int(list(gmaxset1-gminset1)[k]))
			addb+=[add1]
		for a in addb:
			for j in range(2**len(gmaxset2-gminset2)):
				add1=a
				for k in range(len(gmaxset2-gminset2)):
					if j//(2**(len(gmaxset2-gminset2)-k-1))%2==1: add1+=2**(int(list(gmaxset2-gminset2)[k])+N1())
				map[add1]=True
	num=0
	for i in range(4**N1()):
		j=bin(4**N1()-i-1)[2:]
		j=j[::-1]+"0"*(2*N1()-len(j))
		j=int(j,2)
		if map[j]:
			num+=1
			text="     "
			for k in range(N1()):
				if j%2==1: text+="X"
				else: text+="-"
				j=j//2
			text+="  "
			for k in range(N1()):
				if j%2==1: text+="X"
				else: text+="-"
				j=j//2
			print(text)
	print(f"\nTotal: {num} rules\n")
def all_discoverers(command=""):
	a={}
	b={}
	d={}
	for i in g:
		dx,dy=detect_shift(i[5],i[6])
		dx1,dy1,p1,p,mod,gcd3=detect_speed(dx,dy,i[4])
		if exclude(command,dx1,dy1,p1,p,i[1]): continue
		j=authors(i[1])
		for k in j:
			if k in a:
				a[k]+=1
				b[k]+=1/len(j)
				d[k]+=1 if len(j)>1 else 0
			else:
				a[k]=1
				b[k]=1/len(j)
				d[k]=1 if len(j)>1 else 0
	l=12
	for i in a.keys():
		l=max(l,len(i))
	c=sorted(a.items(), key=lambda x: x[1])[::-1]
	print(f"\nAll discoverers of {command}{'' if command=='' else ' '}{pt(2)}:\n")
	print("    Discoverer"+" "*(l-6)+"Total   Partial      Shared\n")
	for i in c:
		pA = i[0]
		pB = str(i[1])
		pC = str(round(b[i[0]], 4))
		pD = str(d[i[0]])
		print("    "+pA+" "*(l-len(pA)+4)+pB+" "*(8-len(pB))+pC+" "*(13-len(pC))+pD)
	print(f"\nTotal: {len(c)} discoverers\n")
def all_gliders(command=""):
	print()
	for i in range(len(g)):
		dx,dy=detect_shift(g[i][5],g[i][6])
		dx1,dy1,p1,p,mod,gcd3=detect_speed(dx,dy,g[i][4])
		if exclude(command,dx1,dy1,p1,p,g[i][1]): continue
		glider(i+1)
		print()
usage_glider=f"""usage:
  glider n        to output the nth known glider
  glider _n       to output the nth row from the database
  glider B3/S23   to list known gliders for this rule (add "=" before additional options)
  glider -string  to list rules having gliders with matching speed and direction
  glider )string  to chart matching gliders for each rule with B0 and without S8
  glider @string  to chart matching gliders for each rule with B2
  glider #string  to chart matching gliders for each rule with B3
  glider @#string to chart matching gliders for each rule with B23
  glider *        to list all gliders
  glider a        to list all discoverers

options for -, @, and # (multiple options must be in the given order):
  n               to chart counts of the number of known gliders (the default)
  u               to chart counts of the number of known unsimplified speeds
  v               to chart counts of the number of known simplified speeds
  p               to chart the maximum known glider unsimplified period
  i               to chart the maximum known glider simplified period
  s               to chart the minimum known glider size
  MMc/NN          to chart only gliders with the given speed
  XX,YYc/PP       to chart only gliders with the given speed (XX is greater than YY)
  d               to chart only gliders that move diagonally
  k               to chart only gliders that move at a knights move or other off-slope
  o               to chart only gliders that move orthogonally
  :PERSON         to chart only gliders discovered by specified person
"""
usage_oscillator=f"""usage:
  glider n        to output the nth known oscillator
  glider _n       to output the nth row from the database
  glider B3/S23   to list known oscillators for this rule (add "=" before additional options)
  glider -string  to list rules having oscillators with matching period
  glider )string  to chart matching oscillators for each rule with B0 and without S8
  glider !string  to chart matching oscillators for each rule with B1
  glider @string  to chart matching oscillators for each rule with B2
  glider #string  to chart matching oscillators for each rule with B3
  glider @#string to chart matching oscillators for each rule with B23
  glider ;string  to chart matching oscillators for each rule without B0, B1, B2 or B3
  glider *        to list all oscillators
  glider a        to list all discoverers

options for -, @, and # (multiple options must be in the given order):
  n               to chart counts of the number of known oscillators (the default)
  p               to chart the maximum known oscillator period
  s               to chart the minimum known oscillator size
  cPP             to chart only oscillator with the given period
  :PERSON         to chart only oscillators discovered by specified person
"""
while True:
	com=input(">>>")
	if ":" in com:
		com,au=com.split(":")
		if au=="": au=disc_0
	else: au=""
	if com.isnumeric():
		if int(com)>len(g): print(f"only {len(g)} {pat_type[type][2]} are known")
		elif com=="0": print("numbering starts from 1")
		else: glider(int(com))
		print()
	elif com.startswith(")"):
		if mode=="OT": create_map("0","12345678","","01234567",com[1:])
		elif mode=="Hex": create_map("0","123456","","012345",com[1:])
		elif mode=="von_Neumann": create_map("0","1234","","0123",com[1:])
	elif com.startswith("@#"):
		if mode=="OT": create_map("23","45678","","012345678",com[1:])
		elif mode=="Hex": create_map("23","456","","0123456",com[1:])
		elif mode=="von_Neumann": create_map("23","4","","01234",com[1:])
	elif com.startswith("!"):
		if mode=="OT": create_map("1","2345678","","012345678",com[1:])
		elif mode=="Hex": create_map("1","23456","","0123456",com[1:])
		elif mode=="von_Neumann": create_map("1","234","","01234",com[1:])
	elif com.startswith("@"):
		if mode=="OT": create_map("2","45678","","012345678",com[1:])
		elif mode=="Hex": create_map("2","3456","","0123456",com[1:])
		elif mode=="von_Neumann": create_map("2","34","","01234",com[1:])
	elif com.startswith("#"):
		if mode=="OT": create_map("3","45678","","012345678",com[1:])
		elif mode=="Hex": create_map("3","456","","0123456",com[1:])
		elif mode=="von_Neumann": create_map("3","4","","01234",com[1:])
	elif com.startswith(";"):
		if mode=="OT": create_map("","45678","","012345678",com[1:])
		elif mode=="Hex": create_map("","456","","0123456",com[1:])
		elif mode=="von_Neumann": create_map("","4","","01234",com[1:])
	elif com.startswith("-"):
		create_list(com[1:])
	elif "/" in com and ((not "c/" in com) or "B" in com):
		if "=" in com: com = com.split("=")
		else: com = [com,""]
		comB, comS=com[0].replace(postfix[mode],"").replace("B","").replace("S","").split("/")
		for k in glider_impossible:
			if (set(k[0]) <= set(comB) <= set(k[2])) and (set(k[1]) <= set(comS) <= set(k[3])):
				print(k[4])
				break
		else:
			no=True
			for i in range(len(g)):
				if glider(i+1,com[0],com[1]):
					print()
					no=False
				if "0" in comB:
					if glider(i+1,"B"+inv_trans(comS)+"/S"+inv_trans(comB)+postfix[mode]):
						print()
						no=False
			if no: print("No gliders are known.")
	elif com.startswith("_"):
		try: print(gt[int(com[1:])-1])
		except: print("Invalid command!")
	elif com.startswith("*"): all_gliders(com[1:])
	elif com.startswith("a"): all_discoverers(com[1:])
	elif com in ["","c","help","usage","?"]:
		if type=="glider": print(usage_glider)
		else: print(usage_oscillator)
	elif com in ["update","refresh","reload"]:
		try:
			load_db()
			print("Database reloaded")
		except:
			print("Failed to reload database")
	elif com in ["quit","exit"]: break
To read a specific database, rewrite line 4 like [file = "oscillators.db"].
Test commands:

Code: Select all

#####For new-gliders.db
B38/S23=2,1c/6   #the Sprayer
a2,1c/5   #all discoverers of (2,1)c/5 spaceships
a:   #number of gliders discovered by unknown people
#v   #counts of the numbers of known glider simplified speeds in B3 rules
###For example: B3/S35 has 3 simplified speeds (c/2o, c/3o, c/4o)
#v   #counts of the numbers of known glider unsimplified speeds in B3 rules
###For example: B3/S35 has 5 unsimplified speeds (c/2o, 2c/4o, 4c/8o, c/3o, c/4o)
_22222   #DB string of an oblique spaceship in Pedestrian Life
#####For oscillators.db
B3/S23=c43   #p43 Snark loop
#c41   #map of B3 rules with known p41 oscillators
B3/S23:carybe   #p36 shuttle
To do:
  • Solve potential issues with B0 maps
  • Rework "-" option and implement "+" option (to list redundant gliders/oscillators)
  • Figure out which rules cannot contain oscillators/spaceships and rework "glider_impossible" for databases other than hex-gliders.db
  • Add option to search for pattern by name
  • Make code more readable
Can we complete 14-in-9 (Completed by me and Kazyan in 2022) and 15-in-10 (9 still lifes left) in CGoL?

The latest version of hex-gliders.db have 249 spaceships from OT hexagonal rules.

My CA

Drone_Better
Posts: 17
Joined: December 1st, 2021, 5:16 am

Re: new-glider.py

Post by Drone_Better » July 24th, 2022, 5:44 pm

I noticed that every possibility of com.startswith() has the second parameter of create_map is a run of digits, the first of which is determined by the startswith, but line 480 seems to be an exception to this (beginning with 4 instead of 3 like the rest in its startswith), is this intentional? I don't know what it does but it seems like an oversight to me.

User avatar
May13
Posts: 426
Joined: March 11th, 2021, 8:33 am

Re: new-glider.py

Post by May13 » July 24th, 2022, 10:13 pm

Drone_Better wrote:
July 24th, 2022, 5:44 pm
I noticed that every possibility of com.startswith() has the second parameter of create_map is a run of digits, the first of which is determined by the startswith, but line 480 seems to be an exception to this (beginning with 4 instead of 3 like the rest in its startswith), is this intentional? I don't know what it does but it seems like an oversight to me.

Code: Select all

	elif com.startswith("@"):
		if mode=="OT": create_map("2","45678","","012345678",com[1:])
                                               ^
		elif mode=="Hex": create_map("2","3456","","0123456",com[1:])
		elif mode=="von_Neumann": create_map("2","34","","01234",com[1:])
This is intentional.
OT: command create_map("2","345678","","012345678",com[1:]) will display B23 rules that don't appear in glider.c. You can use "@#" command to create a B23 map.
Hex and von_Neumann: due to small number of these rules, I also included B23.
create_map works like this:

Code: Select all

create_map(main B transitions, optional B transitions, main S transitions, optional S transitions, options)
Not related to question: here's a minor fix for slice indexes:

Code: Select all

#elif com.startswith("@#"):
#		if mode=="OT": create_map("23","45678","","012345678",com[1:])
#		elif mode=="Hex": create_map("23","456","","0123456",com[1:])
#		elif mode=="von_Neumann": create_map("23","4","","01234",com[1:])
elif com.startswith("@#"):
		if mode=="OT": create_map("23","45678","","012345678",com[2:])
		elif mode=="Hex": create_map("23","456","","0123456",com[2:])
		elif mode=="von_Neumann": create_map("23","4","","01234",com[2:])
Can we complete 14-in-9 (Completed by me and Kazyan in 2022) and 15-in-10 (9 still lifes left) in CGoL?

The latest version of hex-gliders.db have 249 spaceships from OT hexagonal rules.

My CA

User avatar
LaundryPizza03
Posts: 1886
Joined: December 15th, 2017, 12:05 am
Location: Unidentified location "https://en.wikipedia.org/wiki/Texas"

Re: new-glider.py

Post by LaundryPizza03 » July 25th, 2022, 10:02 pm

What is the full syntax, and how do I compile it? Is there a built-in usage guide?

Code: Select all

x = 4, y = 3, rule = B3-q4z5y/S234k5j
2b2o$b2o$2o!
LaundryPizza03 at Wikipedia

The latest edition of new-gliders.db.txt and oscillators.db.txt have 35296 spaceships and 1451 oscillators from outer-totalistic rules. You are invited to help!

User avatar
May13
Posts: 426
Joined: March 11th, 2021, 8:33 am

Re: new-glider.py

Post by May13 » July 26th, 2022, 8:39 am

LaundryPizza03 wrote:
July 25th, 2022, 10:02 pm
What is the full syntax, and how do I compile it? Is there a built-in usage guide?
I use this command to run the script in Cygwin:

Code: Select all

python3 new-glider.py
new-glider.py will execute commands (separated by [Enter]) until one of "quit", "exit", [Ctrl]+[C], [Ctrl]+[D] is entered.
To see a built-in usage, run one of these commands: ["","c","help","usage","?"]
Example:

Code: Select all

$ python3 new-glider.py
>>>
usage:
  glider n        to output the nth known glider
  glider _n       to output the nth row from the database
  glider B3/S23   to list known gliders for this rule (add "=" before additional options)
  glider -string  to list rules having gliders with matching speed and direction
  glider )string  to chart matching gliders for each rule with B0 and without S8
  glider @string  to chart matching gliders for each rule with B2
  glider #string  to chart matching gliders for each rule with B3
  glider @#string to chart matching gliders for each rule with B23
  glider *        to list all gliders
  glider a        to list all discoverers

options for -, @, and # (multiple options must be in the given order):
  n               to chart counts of the number of known gliders (the default)
  u               to chart counts of the number of known unsimplified speeds
  v               to chart counts of the number of known simplified speeds
  p               to chart the maximum known glider unsimplified period
  i               to chart the maximum known glider simplified period
  s               to chart the minimum known glider size
  MMc/NN          to chart only gliders with the given speed
  XX,YYc/PP       to chart only gliders with the given speed (XX is greater than YY)
  d               to chart only gliders that move diagonally
  k               to chart only gliders that move at a knights move or other off-slope
  o               to chart only gliders that move orthogonally
  :PERSON         to chart only gliders discovered by specified person

>>>22222
#C Glider 22222, (5,2)c/190
#C Discovered by David S. Miller, 2016
#C
#C B012345678 S012345678
#C  ---X----X  --XX-----
#C
x = 35, y = 15, rule = B38/S23
20b2o3b2o$20bo3b3o5b2o$20bo2bob2o5bobo$20b6o7bo$25bo$25b2o4$2o3b2o5b2o$o
3b3o4b5o$o2bob2o4bo4bo$6o5b3o2bo$5bo6bo2b2o$5b2o6b2o!

>>>ac/12o

All discoverers of c/12o gliders:

    Discoverer        Total   Partial      Shared

    :UNKNOWN:         202     202.0        0
    Josh Ball         1       1.0          0
    muzik             1       1.0          0
    LaundryPizza03    1       1.0          0

Total: 4 discoverers

>>>*c/12o:muzik

#C Glider 22181, c/12 orthogonal (period 24)
#C Discovered by muzik, 2017
#C
#C B012345678 S012345678
#C  X-X- -X-   -X- -----
#C
x = 35, y = 1, rule = B026/S1
7o2bobo2b3o2bo2bo3b3o2bo2bo!

>>>_22181
:muzik, 2017:B026/S1:B02468/S13:24:2:0:35:1:7o2bobo2b3o2bo2bo3b3o2bo2bo!
>>>exit

I think this version of new-glider.py is not a stable release. Right now there are no implementation of list of redundant gliders.
I'll likely need help figuring out the rules where patterns with certain properties can't exist, especially oscillators and still lifes.
Can we complete 14-in-9 (Completed by me and Kazyan in 2022) and 15-in-10 (9 still lifes left) in CGoL?

The latest version of hex-gliders.db have 249 spaceships from OT hexagonal rules.

My CA

User avatar
LaundryPizza03
Posts: 1886
Joined: December 15th, 2017, 12:05 am
Location: Unidentified location "https://en.wikipedia.org/wiki/Texas"

Re: new-glider.py

Post by LaundryPizza03 » July 26th, 2022, 12:59 pm

May13 wrote:
July 26th, 2022, 8:39 am
I think this version of new-glider.py is not a stable release. Right now there are no implementation of list of redundant gliders.
I'll likely need help figuring out the rules where patterns with certain properties can't exist, especially oscillators and still lifes.
Known rules without spaceships are listed here. For rules with no still lifes, see the list of immortal rules at Eppstein 2009and then take the vanishing dual.

Code: Select all

x = 4, y = 3, rule = B3-q4z5y/S234k5j
2b2o$b2o$2o!
LaundryPizza03 at Wikipedia

The latest edition of new-gliders.db.txt and oscillators.db.txt have 35296 spaceships and 1451 oscillators from outer-totalistic rules. You are invited to help!

User avatar
LaundryPizza03
Posts: 1886
Joined: December 15th, 2017, 12:05 am
Location: Unidentified location "https://en.wikipedia.org/wiki/Texas"

Re: new-glider.py

Post by LaundryPizza03 » July 29th, 2022, 4:21 pm

Where can I obtain copies of hex-oscillators.db, vn-gliders.db, and vn-oscillators.db?

EDIT: After changing all the filename suffixes to ".db.txt", how do I resolve this?

Code: Select all

> python3 new-glider.py
Traceback (most recent call last):
  File "~/Documents/New Gliders DB/new-glider.py", line 13, in <module>
    mode=files[file][0] #OT #Hex #von_Neumann
KeyError: 'new-gliders.db'

Code: Select all

x = 4, y = 3, rule = B3-q4z5y/S234k5j
2b2o$b2o$2o!
LaundryPizza03 at Wikipedia

The latest edition of new-gliders.db.txt and oscillators.db.txt have 35296 spaceships and 1451 oscillators from outer-totalistic rules. You are invited to help!

User avatar
May13
Posts: 426
Joined: March 11th, 2021, 8:33 am

Re: new-glider.py

Post by May13 » July 29th, 2022, 8:58 pm

LaundryPizza03 wrote:
July 29th, 2022, 4:21 pm
Where can I obtain copies of hex-oscillators.db, vn-gliders.db, and vn-oscillators.db?

EDIT: After changing all the filename suffixes to ".db.txt", how do I resolve this?

Code: Select all

> python3 new-glider.py
Traceback (most recent call last):
  File "~/Documents/New Gliders DB/new-glider.py", line 13, in <module>
    mode=files[file][0] #OT #Hex #von_Neumann
KeyError: 'new-gliders.db'
I don't know about the existence of hex-oscillators.db, vn-gliders.db or vn-oscillators.db. I just prepared this script to read such files.
About KeyError: most likely the problem is in "file" from line 4. In your case line 4 should be replaced with

Code: Select all

file="new-gliders.db.txt" #Name of database
Can we complete 14-in-9 (Completed by me and Kazyan in 2022) and 15-in-10 (9 still lifes left) in CGoL?

The latest version of hex-gliders.db have 249 spaceships from OT hexagonal rules.

My CA

User avatar
LaundryPizza03
Posts: 1886
Joined: December 15th, 2017, 12:05 am
Location: Unidentified location "https://en.wikipedia.org/wiki/Texas"

Re: new-glider.py

Post by LaundryPizza03 » July 30th, 2022, 9:44 pm

May13 wrote:
July 29th, 2022, 8:58 pm
LaundryPizza03 wrote:
July 29th, 2022, 4:21 pm
Where can I obtain copies of hex-oscillators.db, vn-gliders.db, and vn-oscillators.db?

EDIT: After changing all the filename suffixes to ".db.txt", how do I resolve this?

Code: Select all

> python3 new-glider.py
Traceback (most recent call last):
  File "~/Documents/New Gliders DB/new-glider.py", line 13, in <module>
    mode=files[file][0] #OT #Hex #von_Neumann
KeyError: 'new-gliders.db'
I don't know about the existence of hex-oscillators.db, vn-gliders.db or vn-oscillators.db. I just prepared this script to read such files.
About KeyError: most likely the problem is in "file" from line 4. In your case line 4 should be replaced with

Code: Select all

file="new-gliders.db.txt" #Name of database
Thanks, but it's not returning anything from the database, e.g. "glider B3/S13" returns no results.

Code: Select all

x = 4, y = 3, rule = B3-q4z5y/S234k5j
2b2o$b2o$2o!
LaundryPizza03 at Wikipedia

The latest edition of new-gliders.db.txt and oscillators.db.txt have 35296 spaceships and 1451 oscillators from outer-totalistic rules. You are invited to help!

User avatar
May13
Posts: 426
Joined: March 11th, 2021, 8:33 am

Re: new-glider.py

Post by May13 » July 30th, 2022, 10:50 pm

LaundryPizza03 wrote:
July 30th, 2022, 9:44 pm
Thanks, but it's not returning anything from the database, e.g. "glider B3/S13" returns no results.
Oops. Seems like the word "glider" from usage should be removed. Try "B3/S13" instead of "glider B3/S13".

Code: Select all

>>>glider B3/S13
No gliders are known.
>>>B3/S13
#C The Creeper (glider 860), c/4 orthogonal
#C Discovered by Nathan Thompson, 1994, and Jean-Claude Heudin, 1996
#C
#C B012345678 S012345678
#C  ---X---    -X-X  -
#C
x = 5, y = 3, rule = B3/S13
3o$3b2o$3o!

#C The Sidewinder (glider 1194), c/4 diagonal (period 4/2)
#C Discovered by Nathan Thompson, 1994
#C
#C B012345678 S012345678
#C  ---X- -     X-X--
#C
x = 5, y = 4, rule = B3/S13
2o2$2b3o$3bo!

#C The Fighter (glider 3561), c/6 orthogonal
#C Discovered by Alan Hensel, 1994, and Jean-Claude Heudin, 1996
#C
#C B012345678 S012345678
#C  ---X---    -X-X- -
#C
x = 7, y = 3, rule = B3/S13
bo2b3o$2o$bo2b3o!

#C Glider 17117, c/2 orthogonal
#C
#C B012345678 S012345678
#C  ---X---    -X-X--
#C
x = 23, y = 11, rule = B3/S13
9bo3bo$3b2o4b2ob2o4b2o$bo7b2ob2o7bo$b2o4b2o5b2o4b2o$2bo5b2o3b2o5bo$2b2o
2bo9bo2b2o$3b3obo2bobo2bob3o$4bobo3bobo3bobo$2bo5b2obob2o5bo$3ob2ob2ob3o
b2ob2ob3o$bo3b2o9b2o3bo!

#C Glider 18270, c/3 orthogonal
#C
#C B012345678 S012345678
#C  ---X---    -X-X---
#C
x = 13, y = 27, rule = B3/S13
b3o5b3o$2bo7bo$2o9b2o$3b2o3b2o$3b2o3b2o$bobo5bobo$o3bo3bo3bo$3obo3bob3o$
bo2b2ob2o2bo$o3bo3bo3bo$b3o5b3o$2bo3bo3bo$2bo3bo3bo$2bo7bo$3b2obob2o$4bo
3bo$4bo3bo$6bo$5b3o$4bo3bo$5bobo$5bobo$4bo3bo2$3b2o3b2o$6bo$5bobo!

>>>
Can we complete 14-in-9 (Completed by me and Kazyan in 2022) and 15-in-10 (9 still lifes left) in CGoL?

The latest version of hex-gliders.db have 249 spaceships from OT hexagonal rules.

My CA

User avatar
LaundryPizza03
Posts: 1886
Joined: December 15th, 2017, 12:05 am
Location: Unidentified location "https://en.wikipedia.org/wiki/Texas"

Re: new-glider.py

Post by LaundryPizza03 » August 4th, 2022, 6:16 pm

new-glider.py crashed while attempting to generate a chart. This didn't happen before.

Code: Select all

>>>#1c/5o
Traceback (most recent call last):
  File "/Users/gb/Documents/New Gliders DB/new-glider.py", line 484, in <module>
    if mode=="OT": create_map("3","45678","","012345678",com[1:])
  File "/Users/gb/Documents/New Gliders DB/new-glider.py", line 227, in create_map
    dx,dy=detect_shift(i[5],i[6])
IndexError: list index out of range
nvm, just had to remove all the extraneous line breaks in the DB

Code: Select all

x = 4, y = 3, rule = B3-q4z5y/S234k5j
2b2o$b2o$2o!
LaundryPizza03 at Wikipedia

The latest edition of new-gliders.db.txt and oscillators.db.txt have 35296 spaceships and 1451 oscillators from outer-totalistic rules. You are invited to help!

Post Reply