Here's the script. The apgcode-determining part is borrowed from apgsearch. Select a constellation (of 20 cells or less) and run it. The script should output a pattern with all the collisions it knows, or tell you that it could not find any:
Code: Select all
import golly as g
g.setrule("B3/S23")
offset = 0
with open("consts.txt","r") as fl:
consts = (fl.read()[1:-1]).split(", ")
with open("cols.txt","r") as fl:
cols = (fl.read()[2:-2]).split("], [")
i = 0
for i in range(0,len(cols)):
cols[i] = cols[i].split(", ")
def bijoscar(maxsteps):
initpop = int(g.getpop())
initrect = g.getrect()
if (len(initrect) == 0):
return 0
inithash = g.hash(initrect)
for i in xrange(maxsteps):
g.run(1)
if (int(g.getpop()) == initpop):
prect = g.getrect()
phash = g.hash(prect)
if (phash == inithash):
period = i + 1
if (prect == initrect):
return period
else:
return -period
return -1
def canonise():
p = bijoscar(4)
representation = "#"
for i in range(abs(p)):
rect = g.getrect()
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1], 1, 0, 0, 1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1], -1, 0, 0, 1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1]+rect[3]-1, 1, 0, 0, -1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1]+rect[3]-1, -1, 0, 0, -1))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1], 0, 1, 1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1], 0, -1, 1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1]+rect[3]-1, 0, 1, -1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1]+rect[3]-1, 0, -1, -1, 0))
g.run(1)
if (p<0):
prefix = "q"+str(abs(p))
elif (p==1):
prefix = "s"+str(g.getpop())
else:
prefix = "p"+str(p)
return "x"+prefix+"_"+representation
# A subroutine used by canonise:
def canonise_orientation(length, breadth, ox, oy, a, b, c, d):
representation = ""
chars = "0123456789abcdefghijklmnopqrstuvwxyz"
for v in xrange(int((breadth-1)/5)+1):
zeroes = 0
if (v != 0):
representation += "z"
for u in xrange(length):
baudot = 0
for w in xrange(5):
x = ox + a*u + b*(5*v + w)
y = oy + c*u + d*(5*v + w)
baudot = (baudot >> 1) + 16*g.getcell(x, y)
if (baudot == 0):
zeroes += 1
else:
if (zeroes > 0):
if (zeroes == 1):
representation += "0"
elif (zeroes == 2):
representation += "w"
elif (zeroes == 3):
representation += "x"
else:
representation += "y"
representation += chars[zeroes - 4]
zeroes = 0
representation += chars[baudot]
return representation
# Compares strings first by length, then by lexicographical ordering.
# A hash character is worse than anything else.
def compare_representations(a, b):
if (a == "#"):
return b
elif (b == "#"):
return a
elif (len(a) < len(b)):
return a
elif (len(b) < len(a)):
return b
elif (a < b):
return a
else:
return b
pattern = canonise()
if pattern in consts:
g.clear(1)
g.clear(0)
g.setgen("0")
loc = consts.index(pattern)
g.show(str(len(cols[loc])) + " collisions found")
g.setname(pattern)
for e in cols[loc]:
g.putcells(g.parse(e),offset,0)
offset += 50
else:
g.note("No 3 glider collision found for that constellation. Better luck next time")
Code: Select all
x = 267, y = 16, rule = B3/S23
10bo49bo49bo49bo50bo53bo$10bobo47bobo46bo49bo50bo53bo$10b2o48b2o47b3o
47b3o48b3o51b3o$b2o98b2o48b2o$obo47b3o47bobo47bobo$2bo49bo49bo49bo47b
3o$51bo150bo$201bo49bo$251b2o$7b3o240bobo$9bo46b2o48b3o98b2o52b2o$8bo
46bobo50bo97bobo51bobo$57bo49bo100bo53bo$154bo$154b2o$153bobo!
Edit: In case somebody wants to modify/improve it, here's the script that was used to generate the text files. It reads from a gencols output file:
Code: Select all
import golly as g
g.setrule("Life")
FILENAME = "C:/cygwin64/home/Dary Fitrady/gencols/3g.col"
MAX_GENS = 256
MAX_POP = 20
count=0
consts = []
cols = []
def bijoscar(maxsteps):
initpop = int(g.getpop())
initrect = g.getrect()
if (len(initrect) == 0):
return 0
inithash = g.hash(initrect)
for i in xrange(maxsteps):
g.run(1)
if (int(g.getpop()) == initpop):
prect = g.getrect()
phash = g.hash(prect)
if (phash == inithash):
period = i + 1
if (prect == initrect):
return period
else:
return -period
return -1
def canonise():
p = bijoscar(4)
representation = "#"
for i in range(abs(p)):
rect = g.getrect()
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1], 1, 0, 0, 1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1], -1, 0, 0, 1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1]+rect[3]-1, 1, 0, 0, -1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1]+rect[3]-1, -1, 0, 0, -1))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1], 0, 1, 1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1], 0, -1, 1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1]+rect[3]-1, 0, 1, -1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1]+rect[3]-1, 0, -1, -1, 0))
g.run(1)
if (p<0):
prefix = "q"+str(abs(p))
elif (p==1):
prefix = "s"+str(g.getpop())
else:
prefix = "p"+str(p)
return "x"+prefix+"_"+representation
# A subroutine used by canonise:
def canonise_orientation(length, breadth, ox, oy, a, b, c, d):
representation = ""
chars = "0123456789abcdefghijklmnopqrstuvwxyz"
for v in xrange(int((breadth-1)/5)+1):
zeroes = 0
if (v != 0):
representation += "z"
for u in xrange(length):
baudot = 0
for w in xrange(5):
x = ox + a*u + b*(5*v + w)
y = oy + c*u + d*(5*v + w)
baudot = (baudot >> 1) + 16*g.getcell(x, y)
if (baudot == 0):
zeroes += 1
else:
if (zeroes > 0):
if (zeroes == 1):
representation += "0"
elif (zeroes == 2):
representation += "w"
elif (zeroes == 3):
representation += "x"
else:
representation += "y"
representation += chars[zeroes - 4]
zeroes = 0
representation += chars[baudot]
return representation
# Compares strings first by length, then by lexicographical ordering.
# A hash character is worse than anything else.
def compare_representations(a, b):
if (a == "#"):
return b
elif (b == "#"):
return a
elif (len(a) < len(b)):
return a
elif (len(b) < len(a)):
return b
elif (a < b):
return a
else:
return b
for s in open(FILENAME):
count+=1
#if count%100==0:
#g.show(str(count))
g.new("Pattern "+str(count))
rle = s.replace('!','$').replace('.','b').replace('*','o')[:-1]+'!'
pat=g.parse(rle)
g.putcells(pat)
g.run(MAX_GENS)
oldbox = g.getrect()
oldpop = int(g.getpop())
if oldpop < MAX_POP and oldpop > 0:
g.run(4)
#rudimentary stable/low period constellation test
if g.getrect() == oldbox and int(g.getpop()) == oldpop:
apg = canonise()
if apg in consts:
cols[consts.index(apg)].append(rle)
else:
consts.append(apg)
cols.append([rle])
g.new('')
with open("consts.txt","w") as output:
output.write(str(consts))
with open("cols.txt","w") as output:
output.write(str(cols))