Day and Night puffer

For discussion of other cellular automata.
Post Reply
OMIKRON
Posts: 12
Joined: August 17th, 2015, 5:42 pm

Day and Night puffer

Post by OMIKRON » October 5th, 2015, 11:26 am

Hello, i found one puffer on CA "Day and Night". one question: is it new ? :)

Code: Select all

x = 52, y = 11, rule = B3678/S34678
3b2ob2o$2bob3obo5bo3bo10bo11bo$bob5o4b5o5bobo2b2ob5o3b3ob3o3bobo$ob6o
2b8o2b4o2b24obo$29ob22o$32ob18o$ob13o2b11ob15o2b4obo$b2obob9o4b11o5b3o
b3o3bob4o$5b3ob5obo5b2o9bo5bo7b4o$4bobobo4b2o9bo20bob4o$11bo34b2o!

User avatar
Xenonquark
Posts: 24
Joined: October 3rd, 2015, 12:49 pm
Location: Somewhere on Earth

Re: Day and Night puffer

Post by Xenonquark » October 5th, 2015, 11:36 am

I would consider it to be a wickstretcher.
Twelve plus one is equal to eleven plus two, anagram or not.

OMIKRON
Posts: 12
Joined: August 17th, 2015, 5:42 pm

Re: Day and Night puffer

Post by OMIKRON » October 5th, 2015, 11:42 am

Yes, i know that it's wickstretcher, that it's speed is c/2, that it's period is 20, but it's not so important, i want only to know: is it new?

OMIKRON
Posts: 12
Joined: August 17th, 2015, 5:42 pm

Re: Day and Night puffer

Post by OMIKRON » October 5th, 2015, 1:44 pm

so, is it possible to find it's name and author on pentadecathlon.com ? or it specialize only on game of life?

OMIKRON
Posts: 12
Joined: August 17th, 2015, 5:42 pm

Re: Day and Night puffer

Post by OMIKRON » October 6th, 2015, 6:40 am

Okey, if so then i can say, that this puffer on "Day and Night" is my discovery. Hooray!!!

User avatar
gameoflifeboy
Posts: 474
Joined: January 15th, 2015, 2:08 am

Re: Day and Night puffer

Post by gameoflifeboy » October 6th, 2015, 12:35 pm

This wickstretcher is not new. On its Catagolue page you can see it already occurred in 261 soups: http://catagolue.appspot.com/object/yl2 ... 3678s34678
OMIKRON wrote:so, is it possible to find it's name and author on pentadecathlon.com ? or it specialize only on game of life?
Pentadecathlon only catalogs objects in B3/S23, and only gives a comprehensive list up to 20 bits. If you have an object in another rule, I recommend using my script to find its object page on Catagolue. To run it, copy it and open an instance of Golly with nothing but your pattern on the screen, and click "Run Clipboard". A window should open with a link to your pattern on Catagolue. If you see sample soups, then your pattern was found before.

Code: Select all

# Goes to catagolue and finds an object page for the shown pattern

import golly as g
import hashlib
from glife import rect

max_finite_period = 500

def canonise(duration):

    representation = "#"

    # We need to compare each phase to find the one with the smallest
    # description:
    for t in xrange(duration):

        r = rect(g.getrect())
        if r.empty:
            return "0"

        if ((r.wd <= 40) & (r.ht <= 40)):
            # Fits within a 40-by-40 bounding box, so eligible to be canonised.
            # Choose the orientation which results in the smallest description:
            representation = compare_representations(representation, canonise_orientation(r.wd, r.ht, r.x, r.y, 1, 0, 0, 1))
            representation = compare_representations(representation, canonise_orientation(r.wd, r.ht, r.x+r.wd-1, r.y, -1, 0, 0, 1))
            representation = compare_representations(representation, canonise_orientation(r.wd, r.ht, r.x, r.y+r.ht-1, 1, 0, 0, -1))
            representation = compare_representations(representation, canonise_orientation(r.wd, r.ht, r.x+r.wd-1, r.y+r.ht-1, -1, 0, 0, -1))
            representation = compare_representations(representation, canonise_orientation(r.ht, r.wd, r.x, r.y, 0, 1, 1, 0))
            representation = compare_representations(representation, canonise_orientation(r.ht, r.wd, r.x+r.wd-1, r.y, 0, -1, 1, 0))
            representation = compare_representations(representation, canonise_orientation(r.ht, r.wd, r.x, r.y+r.ht-1, 0, 1, -1, 0))
            representation = compare_representations(representation, canonise_orientation(r.ht, r.wd, r.x+r.wd-1, r.y+r.ht-1, 0, -1, -1, 0))

        g.run(1)

    g.setgen('0')

    return 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

# Gets the period of an interleaving of degree-d polynomials:
def deepperiod(sequence, maxperiod, degree):

    for p in xrange(1, maxperiod, 1):

        good = True

        for i in xrange(maxperiod):

            diffs = [0] * (degree + 2)
            for j in xrange(degree + 2):

                diffs[j] = sequence[i + j*p]

            # Produce successive differences:
            for j in xrange(degree + 1):
                for k in xrange(degree + 1):
                    diffs[k] = diffs[k] - diffs[k + 1]

            if (diffs[0] != 0):
                good = False
                break

        if (good):
            return p
    return -1

# Analyses a linear-growth pattern, returning a hash:
def linearlyse(maxperiod):

    poplist = [0]*(3*maxperiod)

    for i in xrange(3*maxperiod):

        g.run(1)
        poplist[i] = int(g.getpop())

    p = deepperiod(poplist, maxperiod, 1)

    if (p == -1):
        return "unidentified"

    difflist = [0]*(2*maxperiod)

    for i in xrange(2*maxperiod):

        difflist[i] = poplist[i + p] - poplist[i]

    q = deepperiod(difflist, maxperiod, 0)

    moments = [0, 0, 0]

    for i in xrange(p):

        moments[0] += (poplist[i + q] - poplist[i])
        moments[1] += (poplist[i + q] - poplist[i]) ** 2
        moments[2] += (poplist[i + q] - poplist[i]) ** 3

    prehash = str(moments[1]) + "#" + str(moments[2])

    # Linear-growth patterns with growth rate zero are clearly errors!
    if (moments[0] == 0):
        return "unidentified"

    return "yl" + str(p) + "_" + str(q) + "_" + str(moments[0]) + "_" + hashlib.md5(prehash).hexdigest()

def simple_osc(r, h, p):
    rect = g.getrect()
    hash = g.hash(rect)
    pop = g.getpop()
    if ((r[2] != rect[2]) | (r[3] != rect[3])):
        return False
    if (h != hash):
        return False
    if (p != pop):
        return False

    return True

def encode(maxperiod):
    period = 0
    irect = g.getrect()
    ihash = g.hash(irect)
    ipop = g.getpop()
    ipatt = g.getcells(irect)

    oscillating = False
    while not oscillating:
        if (period == maxperiod):
            g.setgen('0')
            repr = linearlyse(1500)
            if repr == "unidentified":
                g.exit("Object encoding failed.")
            return repr
        g.run(1)
        period += 1
        if (simple_osc(irect, ihash, ipop)):
            oscillating = True
            crect = g.getrect()
            cpatt = g.getcells(crect)
            for i in xrange(0, int(ipop), 2):
                if ((ipatt[i] - irect[0] == cpatt[i] - crect[0]) \
                  & (ipatt[i+1] - irect[1] == cpatt[i+1] - crect[1])):
                    continue
                oscillating = False
                break

    if ((irect[0] == crect[0]) & (irect[1] == crect[1])):
        if (period == 1):
            return "xs" + str(ipop) + '_' + canonise(period)
        else:
            return "xp" + str(period) + '_' + canonise(period)
    else:
        return "xq" + str(period) + '_' + canonise(period)

def grule():
    return g.getrule().split(":")[0].replace('/', '').replace('B', 'b').replace('S', 's')

def return_url(maxperiod):
    apgcode = encode(maxperiod)
    rule = grule()
    return "http://catagolue.appspot.com/object/" + apgcode + "/" + rule

def display_link():
    url = return_url(max_finite_period)
    htmlfile = g.getdir('temp') + 'object-page.html'
    f = open(htmlfile, 'w')
    f.write('<html>\n<title>Catagolue page for object</title>\n')
    f.write('<body><a href="' + url + '">' + url + '</a></body>\n')
    f.write('</html>')
    f.close()
    g.show('All done!')
    g.open(htmlfile)

display_link()

OMIKRON
Posts: 12
Joined: August 17th, 2015, 5:42 pm

Re: Day and Night puffer

Post by OMIKRON » October 6th, 2015, 3:07 pm

Thank you, man! =)

Post Reply