Serizawa - Linear Self Replicator.
Posted: March 23rd, 2014, 6:54 pm
Serizawa rule is perfect for self replicators and universal constructors, but until now there was no known specific examples of such. Here is a working Universal Constructor based self replicator (Geminoid) in Serizawa.
It's P13,362,290 with (2444, 3219) step.
The Geminoid is attached. You can also run the script directly (you need to setup Serizawa rule in golly first and run the script, it takes about 5-10 min):
It's P13,362,290 with (2444, 3219) step.
The Geminoid is attached. You can also run the script directly (you need to setup Serizawa rule in golly first and run the script, it takes about 5-10 min):
Code: Select all
import golly as g
class Glider:
def __init__(self, x, y, dx, dy, state, gen):
self.x = x
self.y = y
self.gen = gen
self.state = state
self.dx = dx
self.dy = dy
def Place(self):
if self.dx == 0:
gld = g.parse(".B$A.A!", -1, 0, 1, 0, 0, self.dy)
else:
gld = g.parse("A$.B$A!", -self.dx, -1, self.dx, 0, 0, 1)
gld = g.evolve(gld, self.state)
g.putcells(gld, self.x, self.y)
class Stopper:
def __init__(self, gld, dist):
self.x = gld.x + dist * gld.dx
self.y = gld.y - dist * gld.dy
def Place(self):
b = g.parse("A!", 0, 0, 1, 0, 0, 1)
g.putcells(b, self.x, self.y)
self.Register(data)
def Register(self, data):
data.append([self.x, self.y, 0])
class TripleSplitter:
def __init__(self, gld, dist):
self.dist = dist
self.gld = gld
self.x = gld.x + dist * gld.dx
self.y = gld.y - dist * gld.dy
self.fgld = Glider(self.x + 3 * gld.dx, self.y - 3 * gld.dy, gld.dx, gld.dy, 0, 5 + gld.gen + dist * 2 + gld.state)
self.rgld = Glider(self.x + 4 * gld.dy - gld.dx, self.y + gld.dy + 4 * gld.dx, gld.dy, -gld.dx, 0, 5 + gld.gen + dist * 2 + gld.state)
self.lgld = Glider(self.x - 4 * gld.dy - gld.dx, self.y + gld.dy - 4 * gld.dx, -gld.dy, gld.dx, 0, 5 + gld.gen + dist * 2 + gld.state)
def Place(self):
b = g.parse("A.A2$A.A!", 0, 0, self.gld.dy, 0, 0, self.gld.dx)
g.putcells(b, self.x - self.gld.dy, self.y - self.gld.dx)
self.Register(data)
def Register(self, data):
if self.gld.dx == 0:
data.append([self.x + 1, self.y, 1])
else:
data.append([self.x, self.y - 1, 2])
class Splitter:
def __init__(self, gld, dist, isRight):
self.split = TripleSplitter(gld, dist)
if isRight:
self.refstop = Stopper(self.split.lgld, 1)
self.refgld = self.split.rgld
else:
self.refstop = Stopper(self.split.rgld, 1)
self.refgld = self.split.lgld
def Place(self):
self.split.Place()
self.refstop.Place()
def Register(self, data):
self.split.Register(data)
self.refstop.Register(data)
class Mirror(Splitter):
def __init__(self, gld, dist, isRight):
Splitter.__init__(self, gld, dist, isRight)
self.fstop = Stopper(self.split.fgld, 1)
def Place(self):
Splitter.Place(self)
self.fstop.Place()
def Register(self, data):
Splitter.Register(self, data)
self.fstop.Register(data)
def PlaceNegative():
total = 10
dist = 29
deltaX = 400
for i in xrange(0, total):
gld = Glider(posx + i * dist, posy, 0, -1, 0, 0)
#gld.Place()
split = Mirror(gld, 10 + i * dist, False)
split.Place()
mir = Splitter(split.refgld, defaultDx + 2 * dist * (total - i), False)
mir.Place()
mir = Mirror(mir.split.fgld, 30 * 10, False)
mir.Place()
def PlaceRef(dist, fact, toplace):
total = 10
delta = [200, 200, 190, 190, 180]
#ds = [[1,0,1,0,0,1,0,1,0,0], [1,0,1,0,0,1,0,1,0,0], [1,0,0,1,0,1,0,0,1,0],[1,0,1,0,0,1,0,1,0,0], [1,0,1,0,0,1,0,1,0,0], [1,0,0,1,0,1,0,0,1,0]]
#ir = 11
#d = 36
ir = 1
d = 52
deltaX = 400
ds = [[1,0,0,1,0,1,0,0,1,0],[1,0,1,0,0,1,0,1,0,0], [1,0,1,0,0,1,0,1,0,0], [1,0,0,1,0,1,0,0,1,0], [1,0,0,1,0,1,0,0,1,0],[1,0,1,0,0,1,0,1,0,0], [1,0,1,0,0,1,0,1,0,0], [1,0,0,1,0,1,0,0,1,0]]
#placement = [[0,0,-1,-1,-1,-1,-1,-1,-1,-1], [0,4,-1,-1,-1,-1,-1,-1,-1,-1], [0,2,72,71,-1,-1,-1,-1,-1,-1], [0,0,-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,10,0,-1,-1,-1,-1,-1,-1], [37 ,41,7,0,51,-1,-1,-1,-1,-1]]
#placement = [[-1,-1,-1,-1,-1,0,0,-1,-1,-1], [-1,-1,-1,-1,-1,0,4,-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,0,2,52 + 2 * (dist - 19),51 + 2 * (dist - 19),-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,0,0,-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,10,0,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,17 + 2 * (dist - 19),21 + 2 * (dist - 19),7,0,31 + 2 * (dist - 19),-1,-1,-1,-1,-1]]
placement = []
placement.extend([[-1,-1,-1,-1,-1,0,2,72,71,-1], [-1,-1,-1,-1,-1,0,0,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,10,0,-1], [-1,-1,-1,-1,-1,37 ,41,7,0,-1]])
placement.extend([[0,2,72,71,-1,-1,-1,-1,-1,-1], [0,0,-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,10,0,-1,-1,-1,-1,-1,-1], [37 ,41,7,0,-1,-1,-1,-1,-1,-1]])
#ds = [[1,0,1,0,0,0,0,0,0,0], [1,0,1,0,0,0,0,0,0,0]]
#placement = [[0,4,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0]]
#for i in xrange(0, 2):
# placement.extend(placement)
# ds.extend(ds)
for i in xrange(0, total):
gld = Glider(posx + i * dist, posy, 0, 1, 0, 0)
split = Splitter(gld, 10 + i * dist, True)
mir = Mirror(split.refgld, defaultDx + 2 * dist * (total - i), True)
if toplace:
split.Place()
mir.Place()
if i >= total / 2:
mir = Mirror(split.split.fgld, dist * total / 2, True)
mir.Place()
mir = Mirror(mir.refgld,10 + 60 * (10 - i), True)
mir.Place()
delMir = 10
mir = Mirror(mir.refgld, delMir, False)
mir.Place()
mir = Mirror(mir.refgld, delMir, False)
mir.Place()
mir = Mirror(mir.refgld, delMir, True)
mir.Place()
mir = Mirror(mir.refgld, 10, True)
mir.Place()
mir = Mirror(mir.refgld, delMir, False)
mir.Place()
mir = Mirror(mir.refgld, delMir, False)
mir.Place()
mir = Mirror(mir.refgld, delMir, True)
mir.Place()
for j in xrange(0, len(placement)):
if placement[j][i] >= 0:
#gld = Glider(posx + i * dist, posy + dist * j + i * fact + placement[j][i], 0, 1, ds[j][i], 0)
gld = Glider(posx + i * dist, posy + total * dist * j + placement[j][i], 0, 1, ds[j][i], 0)
#gld.Place()
if i <= 4:
gld = Glider(posx + i * dist, posy - delta[i], 0, 1, 0, 0)
else:
gld = Glider(posx + deltaX + 201, -157 + posy - i * dist, 1, 0, 0, 0)
if i%5 == 0 or i%5 == 1:
if i <= 4:
gl = Glider(posx + i * dist, 50 + posy - delta[i], 0, 1, 0, 0)
else:
gl = Glider(posx + deltaX + 131, -157 + posy - i * dist, 1, 0, 0, 0)
mir = Mirror(gl, 10, i > 4)
mir.Place()
mir = Mirror(mir.refgld, 6, i <= 4)
mir.Place()
mir = Mirror(mir.refgld, 10, i <= 4)
mir.Place()
mir = Mirror(mir.refgld, 6, i > 4)
mir.Place()
if i%5 == 4:
if i <= 4:
gl = Glider(posx + i * dist, posy - delta[i], 0, 1, 0, 0)
else:
gl = Glider(posx + 471, -157 + posy - i * dist, 1, 0, 0, 0)
mir = Mirror(gl, 0, i > 4)
mir.Place()
mir = Mirror(mir.refgld, 5, i <= 4)
mir.Place()
if i%5 ==0 or i%5 == 2:
mir = Mirror(gld, 19, i <= 4)
mir.Place()
sp = Splitter(gld, 0, i > 4)
sp.Place()
mir = Mirror(sp.refgld, 6, i <= 4)
mir.Place()
mir = Mirror(mir.refgld, 6, i <= 4)
mir.Place()
if i%5 == 1 or i%5 == 3:
mir = Mirror(gld, 19, i > 4)
mir.Place()
ddX = 0
ddY = 0
if toplace:
ddX = 1031
ddY = 774
b = g.parse("A!")
g.putcells(b, 11 + posx + (dist - 17) / 2, -ddY-250 + posy)
data.append([11 + posx + (dist - 17) / 2, -ddY-250 + posy, 0])
data.append([ddX + defaultDx + deltaX - 682 + posx + (dist - 17) / 2, -319 + posy, 0])
g.putcells(b, ddX + defaultDx + deltaX - 682 + posx + (dist - 17) / 2, -319 + posy)
class CommandPlacer():
def __init__(self):
self.loc = 0
self.dist = 29
self.cellLoc = [0, 0]
self.lastCmd = -1
self.lastDir = -1
def Push(self, dir):
if not(self.lastCmd == 0 and self.lastDir == dir):
self.loc += 150
ds = [[1,0],[1,0]]
pl = [[0,0], [0,4]]
spacing = [40, 40]
self.Place(ds, pl, spacing, dir)
self.cellLoc[dir] += 2
self.lastCmd = 0
self.lastDir = dir
def PullSequence(self, dir, shoot):
self.loc += 150
pl = [[0,2,72,71,-1], [0,0,-1,-1,-1], [-1,-1,10,0,-1], [37 ,41,7,0,51 * shoot]]
ds = [[1,0,0,1,0],[1,0,1,0,0], [1,0,1,0,0], [1,0,0,1,0]]
spacing = [60, 80, 58, 40]
self.Place(ds, pl, spacing, dir)
self.cellLoc[dir] -= 31
def Pull(self, dir):
self.PullSequence(dir, 1)
self.lastCmd = 1
self.lastDir = dir
self.loc += 150
def Shoot(self, dir):
self.PullSequence(dir, -1)
self.lastCmd = 2
self.lastDir = dir
self.loc += 150
def CreateBlock(self):
self.loc += 150
#pltemp = [[0,2,72,71,-1], [0,0,-1,-1,-1], [-1,-1,10,0,-1], [37 ,41,7,0,-1]]
ds = [[1,0,0,1,0, 1,0,0,1,0],[1,0,1,0,0, 1,0,0,1,0], [1,0,0,1,0, 1,0,0,1,0],[1,0,1,0,0, 1,0,0,1,0],[1,0,1,0,0, 1,0,1,0,0], [1,0,0,1,0, 1,0,0,1,0],[1,0,1,0,0, 1,0,0,1,0], [1,0,0,1,0, 0,1,1,0,0]]
pl = [[0,2,72,71,-1,-1,-1,-1,-1,-1], [0,0,-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,0,2,72,71,-1], [-1,-1,-1,-1,-1,0,0,-1,-1,-1]]
pl.extend([[-1,-1,10,0,-1,-1,-1,-1,-1,-1], [37 ,41,7,0,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,10,1,-1], [-1,-1,-1,-1,-1,37,42,8,0,-1]])
spacing = [150, 150, 150, 150, 58, 39, 58, 90]
self.Place(ds, pl, spacing, 0)
self.cellLoc[0] -= 31
self.cellLoc[1] -= 31
self.lastCmd = 3
self.lastDir = -1
self.loc += 150
def Place(self, ds, pl, spacing, dir):
for j in xrange(0, len(pl)):
for i in xrange(0, len(pl[0])):
if pl[j][i] >= 0:
gld = Glider(posx + (i + dir * 5) * self.dist, posx + pl[j][i] + self.loc, 0, 1, ds[j][i], 0)
gld.Place()
self.loc += spacing[j]
def Place2Block(self, dir):
self.CreateBlock()
self.Pull(1 - dir)
for j in xrange(0, 14):
self.Push(dir)
for j in xrange(0, 32):
self.Push(1 - dir)
self.CreateBlock()
self.Pull(1 - dir)
for j in xrange(0, 30):
self.Push(1 - dir)
self.Shoot(1 - dir)
def Goto(self, x, y):
while (self.cellLoc[0] > x or self.cellLoc[0]%2 != x%2):
self.Pull(0)
while (self.cellLoc[1] > y or self.cellLoc[1]%2 != y%2):
self.Pull(1)
for j in xrange(0, (y - self.cellLoc[1]) / 2):
self.Push(1)
for j in xrange(0, (x - self.cellLoc[0]) / 2):
self.Push(0)
def Set0(self, x0, x1):
for j in xrange(0, x0):
self.Push(0)
for j in xrange(0, x1):
self.Push(1)
self.cellLoc = [0, 0]
def PlaceData(self, data):
maxXY = -100000
minXY = 100000
for d in data:
if maxXY < d[0] - d[1]:
maxXY = d[0] - d[1]
if minXY > d[0] - d[1]:
minXY = d[0] - d[1]
dXY = []
for i in xrange(minXY, maxXY + 1):
l = []
for d in data:
if i == d[0] - d[1]:
l.append(d)
dXY.append(l)
for i in reversed(dXY):
for d in i:
self.Goto(-d[1], d[0])
if d[2] == 0:
self.CreateBlock()
if d[2] == 1:
self.Place2Block(1)
if d[2] == 2:
self.Place2Block(0)
defaultDx = 900
data = []
posx = (593 + 29) - 1116
posy = 5600 - 6374
PlaceNegative()
posx += (896 + 29) + 600
PlaceRef(29, 0, False)
posx = 0
posy = 0
PlaceRef(29, 0, True)
cmd = CommandPlacer()
cmd.Set0(1113, 410)
cmd.PlaceData(data)
cmd.Pull(0)
cmd.Pull(1)
#cmd = CommandPlacer()
#cmd.Goto(1200, 1200)
#cmd.Place2Block(1)
#posx += 1000
posx = 1716 + (593 + 29) - 1116
posy = 1500 + 5600 - 6374 + int(cmd.loc/2 + 2000)
PlaceNegative()
posx += (896 + 29) + 600
PlaceRef(29, 0, False)
posx = 1716
posy = 1500 + int(cmd.loc/2 + 2000)
PlaceRef(29, 0, True)
'''
posx = 1716 + (593 + 29) - 1116
posy = 1500 + 5600 - 6374 + 3500000
PlaceNegative()
posx += (896 + 29) + 600
PlaceRef(29, 0, False)
posx = 1716
posy = 1500 + 3500000
PlaceRef(29, 0, True)
'''