Help with my scripts

For scripts to aid with computation or simulation in cellular automata.
User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Help with my scripts

Post by Rhombic » April 4th, 2017, 11:01 am

Alright just a mini-disclaimer that the last time I programmed anything was about 5 years ago now and I have never done any Python whatsoever - just kind of familiar with the things common to all programming languages and the sort. Right.

So I was writing this script to aid with the Early Universe-like filling of a space for multi-state rules (you can tell it just attempts to fill with as many cells as you want from each state in a bounding box defined by your selection). Pretty straightforward even if my script probably is ridiculously unoptimised. OK.
Apparently, there is a problem with line 18 ( livecells += s[state]) that does not allow the script to be used at all. I must emphasise my inexperience with treating any kind of list in Python and having forgotten pretty much all previous JS and Java that I learnt.

Code: Select all

import golly as g

if g.empty():
    if g.getwidth() == 0 or g.getheight() == 0:
        g.exit("Select a bounding box to fill.")
else:
    r = g.getrect()
    minx = r[0]
    miny = r[1]
    maxx = minx + r[2] - 1
    maxy = miny + r[3] - 1
    card = r[2] * r[3]
states = g.numstates()
livecells = 1
s = [[] for k in range(states)]
for state in range(1,states):
    s[state] = int(g.getstring("How many state " + str(state) + " cells", "100"))
    livecells += s[state]
pawnlist = {[] for d in range(livecells)}
for state in range(1,states):
    for d in range(s[state]):
        pawnlist.add(state)
ground = card - len(pawnlist)
for dead in range(ground):
    pawnlist.add(0)
for i in range(minx, maxx):
    for j in range(miny, maxy):
                pawn = pawnlist.pop()
                g.setcell(i,j,pawn)
How can I proceed?
Last edited by Rhombic on April 8th, 2017, 9:55 am, edited 4 times in total.
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
dvgrn
Moderator
Posts: 10612
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Help with a script

Post by dvgrn » April 4th, 2017, 11:10 am

Rhombic wrote:I must emphasise my inexperience with treating any kind of list in Python and having forgotten pretty much all previous JS and Java that I learnt.
...
How can I proceed?
You're doing fine as far as the list handling goes, actually. Just add another close parenthesis at the end of line 17.

Python is fairly silly about line numbers in error messages. If the problem is just something missing at the end of a line, the line number quoted in the error is usually the one after the actual problem.

User avatar
calcyman
Moderator
Posts: 2932
Joined: June 1st, 2009, 4:32 pm

Re: Help with a script

Post by calcyman » April 4th, 2017, 11:11 am

You have an unmatched open-parenthesis on the previous line.
What do you do with ill crystallographers? Take them to the mono-clinic!

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with a script

Post by Rhombic » April 4th, 2017, 11:41 am

Thank you - silly mistake but easy to overlook.
Another question: now I have fixed that, there is an error arising from the way I defined the set where it specifies TypeError: unhashable type:'list'

This obviously is because you can't define new sets with unhashable elements contained in them. However, I don't know how to get around this. Any ideas?
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

chris_c
Posts: 966
Joined: June 28th, 2014, 7:15 am

Re: Help with a script

Post by chris_c » April 4th, 2017, 11:59 am

Rhombic wrote:Thank you - silly mistake but easy to overlook.
Another question: now I have fixed that, there is an error arising from the way I defined the set where it specifies TypeError: unhashable type:'list'

This obviously is because you can't define new sets with unhashable elements contained in them. However, I don't know how to get around this. Any ideas?
Running this in Golly should give you an idea for an easier way:

Code: Select all

import golly as g

pawnlist = []
pawnlist += [1] * 1
pawnlist += [2] * 2
pawnlist += [3] * 3

g.show(str(pawnlist))
Also note that range(a, b) runs through the integers a, a+1, ... , b-2, b-1 so the last two for loops in your code probably don't do what you intend.

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with a script

Post by Rhombic » April 4th, 2017, 12:03 pm

chris_c wrote: Running this in Golly should give you an idea for an easier way:

Code: Select all

import golly as g

pawnlist = []
pawnlist += [1] * 1
pawnlist += [2] * 2
pawnlist += [3] * 3

g.show(str(pawnlist))
Also note that range(a, b) runs through the integers a, a+1, ... , b-2, b-1 so the last two for loops in your code probably don't do what you intend.
Hmmm, right, I'll do it via a variable then.
On the other hand, I've just realised that sets don't allow duplicate elements which means that I can't use a set. How can I create an unordered list (or get a random point of the list)?

EDIT: this is the new version of my script, which gives an error "random is not defined":

Code: Select all

import golly as g

if g.empty():
    if g.getwidth() == 0 or g.getheight() == 0:
        g.exit("Select a bounding box to fill.")
else:
    r = g.getrect()
    minx = r[0]
    miny = r[1]
    maxx = minx + r[2] - 1
    maxy = miny + r[3] - 1
    card = r[2] * r[3]
states = g.numstates()
livecells = 1
s = [[] for k in range(states)]
for state in range(1,states):
    berbergoat = int(g.getstring("How many state " + str(state) + " cells", "100"))
    s[state] = berbergoat
    livecells += berbergoat
pawnlist = [[] for d in range(livecells)]
for state in range(1,states):
    for d in range(s[state]):
        pawnlist.append(state)
ground = card - len(pawnlist)
for dead in range(ground):
    pawnlist.append(0)
for i in range(minx, maxx):
    for j in range(miny, maxy):
                pawn = random.choice(pawnlist)
                g.setcell(i,j,pawn)
          
Last edited by Rhombic on April 4th, 2017, 12:30 pm, edited 1 time in total.
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
dvgrn
Moderator
Posts: 10612
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Help with a script

Post by dvgrn » April 4th, 2017, 12:30 pm

Rhombic wrote:How can I create an unordered list (or get a random point of the list)?
Getting a random point is probably better than relying on the unorderedness of a set -- it will probably come out looking suspiciously ordered even though there's no guaranteed order.

Use something like

Code: Select all

                index =  int(random.random() * len(pawnlist))
                pawn = pawnlist.pop(index)
There are lots of other interesting options for different kinds of collections such as double-ended queues, but that's probably overkill for this particular case.

The code at the top was checking if the universe was empty, rather than if there was a selection, so I changed that to test my suggestion:

Code: Select all

import golly as g
import random
r = g.getselrect()
if len(r)==0: g.exit("Select a bounding box to fill.")
minx = r[0]
miny = r[1]
maxx = minx + r[2] - 1
maxy = miny + r[3] - 1
card = r[2] * r[3]

states = g.numstates()
livecells = 1
s = [[] for k in range(states)]
for state in range(1,states):
    s[state] = int(g.getstring("How many state " + str(state) + " cells", "100"))
    livecells += s[state]
pawnlist = []
for state in range(1,states):
    for d in range(s[state]):
        pawnlist.append(state)
ground = card - len(pawnlist)
for dead in range(ground):
    pawnlist.append(0)

for i in range(minx, maxx+1):
    for j in range(miny, maxy+1):
                index =  int(random.random() * len(pawnlist))
                pawn = pawnlist.pop(index)
                g.setcell(i,j,pawn)

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with a script

Post by Rhombic » April 4th, 2017, 12:39 pm

Thank you! That is very useful - I was oblivious to importing random in the first place too!
It works now, but it is remarkably slow, do you know how this could be improved?

Thank you!!!!!
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
dvgrn
Moderator
Posts: 10612
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Help with a script

Post by dvgrn » April 4th, 2017, 1:05 pm

Rhombic wrote:Thank you! That is very useful - I was oblivious to importing random in the first place too!
It works now, but it is remarkably slow, do you know how this could be improved?
Sure. Most of the slowness comes from using pop() to take items out of the middle of a long pawnlist. That requires moving all the items after that removal point... over and over again, and it adds up.

Instead, try something like this at the end:

Code: Select all

random.shuffle(pawnlist)
index=0
for i in range(minx, maxx+1):
    for j in range(miny, maxy+1):
          g.setcell(i,j,pawnlist[index])
          index+=1
The rest of the slowness is from setting a whole bunch of cells to state 0, when they're probably state 0 anyway, or could be made so quickly with g.clear(0). That's a little harder to improve for all cases, though, because sometimes your cells of other states will fill the whole selected area. In that case there aren't any state-0 cells to save time with.

Setting cells one at a time is always going to be somewhat inefficient. One sneaky trick you could do would be to build multistate RLE using the shuffled pawnlist above, and then paste it in with g.parse() at (minx,miny). You don't have to worry about encoding run lengths -- just make a string like

Code: Select all

ABCDEDABAABEEEBABACCC$
DDABCDEDABAABEEEBABAC$
F..F.ABCDEDABAABEFBAB$
.......ABCDEDABAABDEB!
That might speed things up a bit more. Gets a little more complicated if you want to support rules with more than twenty-four states, though.

User avatar
calcyman
Moderator
Posts: 2932
Joined: June 1st, 2009, 4:32 pm

Re: Help with a script

Post by calcyman » April 4th, 2017, 6:47 pm

If you want to use lists as set elements, and don't wish to alter their contents, cast them to 'tuple' instead.
What do you do with ill crystallographers? Take them to the mono-clinic!

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with a script

Post by Rhombic » April 5th, 2017, 3:48 am

@dvgrn,
The random shuffle speeds up the calculation immediately with a massive boost in performance. Very good idea!! Plus you only have to randomise something once too, as a further minor improvement.
calcyman wrote:If you want to use lists as set elements, and don't wish to alter their contents, cast them to 'tuple' instead.
I had been reading about these, but I couldn't see the effective difference between a list and a tuple.
Thank you very much to all of you for helping me out, I have stumbled with very basic points - it's down to practice I guess.

There is a very funny issue that probably arises from using a list to choose what cell to place in each square - a memory error for 16384x16384 grids. I think that unless a radically different approach is taken to create the cells, the bigger the pattern, the longer the list, so if it has something to do with this, there is no way around it.
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
calcyman
Moderator
Posts: 2932
Joined: June 1st, 2009, 4:32 pm

Re: Help with a script

Post by calcyman » April 5th, 2017, 4:06 am

You can't alter the elements of a tuple. So the following is valid with a list but not a tuple:

Code: Select all

a[3] = 7
A tuple of hashable objects is hashable, so it can be used as the key in a dict or set. So the following is valid with a tuple but not a list:

Code: Select all

d = {}
d[a] = 9
You can convert between them by using list() and tuple(). Lists are written with square brackets, whereas tuples are written with round parentheses (and sets/dicts with braces):

Code: Select all

l = [1, 1, 2, 5, 14, 42]
t = (1, 1, 2, 5, 14, 42)
s = {1, 1, 2, 5, 14, 42}
What do you do with ill crystallographers? Take them to the mono-clinic!

User avatar
dvgrn
Moderator
Posts: 10612
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Help with a script

Post by dvgrn » April 5th, 2017, 8:48 am

Rhombic wrote:There is a very funny issue that probably arises from using a list to choose what cell to place in each square - a memory error for 16384x16384 grids. I think that unless a radically different approach is taken to create the cells, the bigger the pattern, the longer the list, so if it has something to do with this, there is no way around it.
Yeah, if you want to shuffle lists that include the zeroes, you're going to be out of luck at some size of selection, depending on your available memory. But to some extent that's true anyway -- Golly can only store just so big of a random pattern.

For relatively sparse fill, where there are enough zero cells that you'll always find one by picking a random location a dozen times or so, you could dump the pawnlist and go back to setting cells individually -- just g.clear(0) it first, and then randomly choose a location for each cell of each color... but getcell() before setting it, and pick a different cell if that one is already nonzero. That will be something between "slower" and "horribly slower" depending on how many zero cells there are.

You might be able to handle somewhat larger selections by storing your pawnlist as a string, or in an array. Or you could write extra code to chop up the selection into smaller safe-size pieces, and give each piece its share of the different cell states. But that's a bit of a can of worms.

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with a script

Post by Rhombic » April 5th, 2017, 10:36 am

Just to practice, I've decided to attempt the Fibonacci (binary) sequence creation in CGoL, as someone requested in the Script request thread.
I have obtained the binary numbers fairly easily, but even after reading how the cell lists work for Golly, I am still unsure about how to plot the cells or create the cell list from the numbers:

Code: Select all

import golly as g

totalnumbers = int(g.getstring("How many Fibonacci numbers:","1"))
decnum = []
binnum = []
cellist = []
init=1
decnum.append(1)
decnum.append(1)
start = 1
start2 = 1
start2prime = 1
for i in range(totalnumbers+1):
    decnum.append(start + start2)
    start2 = start
    start = start + start2prime
    start2prime = start2
for j in range(len(decnum)):
    binnum.append(bin(decnum[j])[2:])
    g.putcells(***list***, 0, init, 0, 0, 0, 0, "or")
    init += 1
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
dvgrn
Moderator
Posts: 10612
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Help with a script

Post by dvgrn » April 5th, 2017, 2:07 pm

Rhombic wrote:Just to practice, I've decided to attempt the Fibonacci (binary) sequence creation in CGoL, as someone requested in the Script request thread.
I have obtained the binary numbers fairly easily, but even after reading how the cell lists work for Golly, I am still unsure about how to plot the cells or create the cell list from the numbers...
You're definitely most of the way there. Just by the way, in Python (or Lua) you can dodge the extra variable start2prime:

Code: Select all

previousfib, fib, fiblist = 1, 1, []
for i in range(100):
  previousfib, fib = fib, previousfib+fib
  fiblist.append(fib)
All the assignments happen at the same time, so you don't have to use an extra variable to store transitional values. But it works just as well the way you're doing it, and maybe it's less confusing.

Each of your binnums has some number of "1" digits in it, so if you wanted to build a cell list, you'd have to iterate through binnum[-1] (the last string in the binnum list) and add an appropriate (x,y) value to your cell list every time you see a "1".

You could build a multistate cell list, and then have one cell per binary digit, with a state of either 0 or 1.
But then you'd have to deal with the weird detail that multistate cell lists always have to be odd-length. In this case there's probably not much point, unless you want to do a "copy"-mode paste and blank out the empty cells.

-- Anyway, it might be simpler to directly setcell() the cells you want to turn ON, one at a time, and skip the cell list entirely. There are lots of other ways to do it, but here's what I ended up with, with orientation matching the sample output in the original request:

Code: Select all

import golly as g
totalnumbers = int(g.getstring("How many Fibonacci numbers:","1000"))
decnum = [1,1]
while len(decnum)<totalnumbers:  # build the list of Fibonacci numbers
  decnum.append(decnum[-2]+decnum[-1])
for j in range(totalnumbers):
    reversedbin=bin(decnum[j])[::-1]  # [::-1] = slice starts at 0, ends at 0, count by -1
    for k in range(len(reversedbin)-2): # the -2 ignores the "b0", now at the end
      if reversedbin[k]=='1':
        g.setcell(-k,j,1)
Of course, the original request asked for a Lua script. [I keep hoping that enough detail will eventually get posted so that someone can figure out what's going wrong with gameoflifemaniac's Python install, but no luck so far...!]

This script would be a little more work in Lua, mainly because I think you'd have to write your own bin() function. And Lua doesn't support arbitrarily long integers, so you might be stuck with Fibonacci numbers only up to 2^32 or 2^53 or 2^64 (depending on how you do it). Fibonacci numbers grow fast, so any of those would be a surprisingly short chunk of fractal.

A nice way around that would be to store all your Fibonacci numbers as binary strings or tables in the first place -- in which case you'd have to write a fibadd() function instead of a bin() function, but your Lua script could build a much bigger Fibonacci fractal.

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with a script

Post by Rhombic » April 5th, 2017, 3:02 pm

Again, many thanks for helping me out, it takes a while until you get the basics right (sometimes). It's funny that the density of any central region in the fractal is exactly 0.25 (larger regions will give it with more precision).
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
dvgrn
Moderator
Posts: 10612
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Help with a script

Post by dvgrn » April 5th, 2017, 3:51 pm

Rhombic wrote:Again, many thanks for helping me out, it takes a while until you get the basics right (sometimes).
There are an awful lot of ways to do the basics in Python, anyway. Thanks for giving me an excuse to play around with the Fibonacci fractal -- I was hoping that script would get written, but it seemed like really good coding practice for someone, and so it seemed like kind of a shame to waste it on me.
Rhombic wrote:It's funny that the density of any central region in the fractal is exactly 0.25 (larger regions will give it with more precision).
That would be really really strange. Most big non-power-of-two binary numbers are about half 1s and half 0s... which is what I'm seeing here. A 1000^2 selection has about 500,000 ON cells in it, not 250,000.

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with a script

Post by Rhombic » April 5th, 2017, 4:09 pm

dvgrn wrote: That would be really really strange. Most big non-power-of-two binary numbers are about half 1s and half 0s... which is what I'm seeing here. A 1000^2 selection has about 500,000 ON cells in it, not 250,000.
EDIT: it uses getrect() instead of getselrect()
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
dvgrn
Moderator
Posts: 10612
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Help with a script

Post by dvgrn » April 5th, 2017, 4:49 pm

Rhombic wrote:
dvgrn wrote: That would be really really strange. Most big non-power-of-two binary numbers are about half 1s and half 0s... which is what I'm seeing here. A 1000^2 selection has about 500,000 ON cells in it, not 250,000.
EDIT: it uses getrect() instead of getselrect()
Ah, got it.

I guess I'm not surprised -- would expect the population of the fractal's bounding box to be just barely bigger than a quarter of its area. The ON cells along the hypotenuse of the triangle are a given, but everything else is half-ON, half-OFF at (pseudo)random.

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with my scripts

Post by Rhombic » April 8th, 2017, 9:46 am

OK, I've tweaked just a bit the glider_destruction.py (by possibly Kazyan? I can't remember) to search for patterns that emit spaceships cleanly.

Code: Select all

# glider_tospaceship.py
# expanded from glider_destruction.py

import golly as g

glider = [[-1, -2, 0, -1, -2, 0, -1, 0, 0, 0], [-2, -2, -1, -1, 0, -1, -2, 0, -1, 0], [-1, -2, -3, -1, -1, -1, -2, 0, -1, 0], [-3, -2, -1, -2, -2, -1, -1, -1, -2, 0]]

collstatus = (g.getpop(), 0, 0, [0, 0]) #(dummy values) box_size, pattern_pos, glider_phase, [glider_x, glider_y]

def form(celllist, num):
   if num not in xrange(8):
      return celllist
   if num >= 4:
      celllist = g.transform(celllist, 0, 0, -1, 0, 0, -1)
      num -= 4
   if num >= 2:
      celllist = g.transform(celllist, 0, 0, 0, 1, -1, 0)
      num -= 2
   if num >= 1:
      celllist = g.transform(celllist, 0, 0, -1, 0, 0, 1)
   return celllist
def trygliders(celllist, distance, num):
   g.new('')
   g.putcells(celllist)
   rect = g.getrect()
   gx = rect[0] - 3 - distance
   gy = rect[1] - 3 - distance
   status = collstatus
   phase = 0
   
   for gphase in glider:
      for w in xrange(rect[2] + 5):
         g.new('')
         g.putcells(celllist)
         g.putcells(gphase, gx + w, gy)
         g.run(1000)
         rectbound = g.getrect()
         g.run(1000)
         pops = len(g.getcells(rectbound))/2
         if pops == 0:
            if len(g.getrect()):
               return (0, num, phase, [gx + w, gy])
         if pops < status[0]:
            if (len(g.getcells(g.getrect()))-len(g.getcells(rectbound))):
               status = (pops, num, phase, [gx + w, gy])
      phase += 1
   return status

celllist = g.getcells(g.getrect())
dist = 0
g.show("Searching for spaceship outputs... press any key to display smallest dirty result.")
while True:
   for num in xrange(8):
      tlist = form(celllist, num)
      collstatus = trygliders(tlist, dist, num)
      event = g.getevent()
      if collstatus[0] == 0 or event.startswith("key"):
         if collstatus[0] == 0:
            g.show("Found clean spaceship output.")
         else:
            g.show("Found dirty output, %d-cell cells left behind." % collstatus[0])
         g.new('')
         g.putcells(form(celllist, collstatus[1]))
         g.putcells(glider[collstatus[2]], collstatus[3][0], collstatus[3][1])
         g.exit()
   dist += 1
After having played around for a bit with it, I'm not sure how to change it any further to do these things:
- Avoid trivial solutions, even for minimal bounding box (i.e. non interacting glider and block, or glider with non-int. glider)
- Extend this to other spaceships instead of just gliders by asking for apgcode and period of a spaceship
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with my scripts

Post by Rhombic » April 27th, 2017, 1:56 pm

It's quite sad that I got to it like this, but funnily enough, while trying to code a glider-activated transparent reaction search (i.e. G+X-->X+Y), from glider-destruction.py, I failed entirely.
In any case, I'll have to find some other way to do the transparent-object search (basically, the idea was to set hash_o to the initial g.hash() and then run the pattern and check whether the hash value of the same bounding box hadn't changed).

Any help appreciated, as always. I'll leave the WIP here:

Code: Select all

# glider_catalyst.py
# expanded from glider_destruction.py

import golly as g

initrect = g.getrect()
hash_o = g.hash(initrect)
pops_o = len(g.getcells(initrect))/2

glider = [[-1, -2, 0, -1, -2, 0, -1, 0, 0, 0], [-2, -2, -1, -1, 0, -1, -2, 0, -1, 0], [-1, -2, -3, -1, -1, -1, -2, 0, -1, 0], [-3, -2, -1, -2, -2, -1, -1, -1, -2, 0]]

collstatus = (g.getpop(), 0, 0, [0, 0]) #(dummy values) box_size, pattern_pos, glider_phase, [glider_x, glider_y]

def form(celllist, num):
   if num not in xrange(8):
      return celllist
   if num >= 4:
      celllist = g.transform(celllist, 0, 0, -1, 0, 0, -1)
      num -= 4
   if num >= 2:
      celllist = g.transform(celllist, 0, 0, 0, 1, -1, 0)
      num -= 2
   if num >= 1:
      celllist = g.transform(celllist, 0, 0, -1, 0, 0, 1)
   return celllist
def trygliders(celllist, distance, num):
   g.new('')
   g.putcells(celllist)
   rect = g.getrect()
   gx = rect[0] - 3 - distance
   gy = rect[1] - 3 - distance
   status = collstatus
   phase = 0
   
   for gphase in glider:
      for w in xrange(rect[2] + 5):
         g.new('')
         g.putcells(celllist)
         g.putcells(gphase, gx + w, gy)
         g.run(1000)
         rectbound = g.getrect()
         g.run(1000)
         pops = len(g.getcells(rectbound))/2
         if pops == pops_o:
            if g.hash(initrect) == hash_o:
               return (0, num, phase, [gx + w, gy])
         if pops < status[0]:
            if not (len(g.getcells(g.getrect()))-len(g.getcells(rectbound))):
               pash = g.hash(initrect)
               status = (pops, num, phase, [gx + w, gy], pash)
      phase += 1
   return status

celllist = g.getcells(g.getrect())
dist = 0
g.show("Searching for transparent reactions... press any key to display smallest dirty result.")
while True:
   for num in xrange(8):
      tlist = form(celllist, num)
      collstatus = trygliders(tlist, dist, num)
      event = g.getevent()
      if collstatus[0] == 0 or event.startswith("key"):
         if collstatus[4] == hash_o:
            g.show("Found clean transparent reaction.")
         else:
            g.show("Found dirty output, %d-cell cells left behind." % collstatus[0])
         g.new('')
         g.putcells(form(celllist, collstatus[1]))
         g.putcells(glider[collstatus[2]], collstatus[3][0], collstatus[3][1])
         g.exit()
   dist += 1
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with my scripts

Post by Rhombic » June 28th, 2017, 6:28 am

I need some help with a very trivial script. There is a bug somewhere, but I can't find it.
The input is a nx1 pattern.
The idea is, for n iterations, repeat the following:
- Call initial pattern A. Evolving it once makes A'.
- Copy the initial g.getrect() but in A'. Go back to A and paste it immediately under it.
- Now we look at the line that is below the previous one. Again, evolve once and copy it. Then go back and paste it under the previous pattern.
etc.

The result for this pattern with 6 (or more) iterations (all cells end up dead after that)

Code: Select all

x = 40, y = 1, rule = B3/S23
8ob3o2b5ob5o2b5o2b6o!
should give this:

Code: Select all

x = 40, y = 7, rule = B3/S23
8ob3o2b5ob5o2b5o2b6o$b6o3bo4b3o3b3o4b3o4b4o$o6bob3o2bo3bobo3bo2bo3bo2b
o4bo$b6o2b3o3b3o3b3o4b3o4b4o$b6o2bobo3b3o3b3o4b3o4b4o$bo4bo2bobo3bobo
3bobo4bobo4bo2bo$bob2obo8bobo3bobo4bobo4bo2bo!
My code does not give this output at all.
Any ideas?

Code: Select all

import golly as g

line = g.getrect()
if line[3] > 1:
    g.exit("Pattern must have a height of one cell")
iterations = int(g.getstring("How many iterations?","1"))
for iteration in range(iterations+1):
    alpha = g.getrect()
    basket = g.getcells(alpha)
    evolved = g.evolve(basket,1)
    g.new('Iteration '+str(iteration))
    g.putcells(evolved)
    for i in range(line[0]+1):
        ncell = g.getcell(i,alpha[1]+iteration-1)
        g.setcell(i,alpha[1]+iteration,ncell)
    newline = [alpha[0], alpha[1]+iteration,alpha[2],1]
    addition = g.getcells(newline)
    g.new('Solution')
    g.putcells(basket)
    g.putcells(addition)
    
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
dvgrn
Moderator
Posts: 10612
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Help with my scripts

Post by dvgrn » June 28th, 2017, 8:42 am

Rhombic wrote:The idea is, for n iterations, repeat the following:
- Call initial pattern A. Evolving it once makes A'.
- Copy the initial g.getrect() but in A'. Go back to A and paste it immediately under it.
- Now we look at the line that is below the previous one. Again, evolve once and copy it. Then go back and paste it under the previous pattern.
etc.

The result for this pattern with 6 (or more) iterations (all cells end up dead after that)
I'm seeing a slightly different result on the fourth new line, when I try that --

Code: Select all

x = 40, y = 5, rule = B3/S23
8ob3o2b5ob5o2b5o2b6o$b6o3bo4b3o3b3o4b3o4b4o$o6bob3o2bo3bobo3bo2bo3bo2b
o4bo$b6o2b3o3b3o3b3o4b3o4b4o$b6ob2obo3b3o3b3o4b3o4b4o!
This give an infinite block-stalactite on the left side, though the right side is identical.

Might the problem be that you're thinking g.new() will create a temporary new layer? Unless you call g.addlayer(), and then g.dellayer() when you're done with the iteration, each g.new() will write over the starting pattern. Looks like some unintended damage like that is being caused.

Your indentation implies that the Solution universe will be created on each iteration -- is it supposed to happen only at the end?

A slight rearrangement of your code, adding and deleting a layer with each iteration, seems to work okay. So the problem is somewhere around there, anyway --

Code: Select all

import golly as g

line = g.getrect()
if line[3] > 1:
    g.exit("Pattern must have a height of one cell")
iterations = int(g.getstring("How many iterations?","1"))

for iteration in range(iterations+1):
    alpha = g.getrect()
    basket = g.getcells(alpha)
    evolved = g.evolve(basket,1)
    g.addlayer()
    g.putcells(evolved)
    newline = [alpha[0], alpha[1]+iteration,alpha[2],1]
    addition = g.getcells(newline)
    g.dellayer()
    g.putcells(addition,0,1)
g.setname('Solution')
You can make it a lot faster by getting rid of the addlayer / dellayer again and extracting the line you're interested in, directly from the evolved cell list -- it's actually going to be the slice of that list, evolved[i:j], where the y value matches the iteration number.

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with my scripts

Post by Rhombic » June 29th, 2017, 5:04 am

dvgrn wrote: I'm seeing a slightly different result on the fourth new line, when I try that --

Code: Select all

correct
Yes, I missed that cell!
dvgrn wrote: Might the problem be that you're thinking g.new() will create a temporary new layer? Unless you call g.addlayer(), and then g.dellayer() when you're done with the iteration, each g.new() will write over the starting pattern. Looks like some unintended damage like that is being caused.
Probably, I was trying to keep the partial solutions copied in different variables but I think they get overwritten or something. In fact, I've realised that it is counting the evolution of each line as if there were no more lines (i.e. only the middle cells survive), which would make sense if the previous line is only kept as part of the solution. That might be it.
I was expecting the Solution to be created every iteration though, the only thing is that I messed up the variables at some point.
dvgrn wrote:

Code: Select all

import golly as g

line = g.getrect()
if line[3] > 1:
    g.exit("Pattern must have a height of one cell")
iterations = int(g.getstring("How many iterations?","1"))

for iteration in range(iterations+1):
    alpha = g.getrect()
    basket = g.getcells(alpha)
    evolved = g.evolve(basket,1)
    g.addlayer()
    g.putcells(evolved)
    newline = [alpha[0], alpha[1]+iteration,alpha[2],1]
    addition = g.getcells(newline)
    g.dellayer()
    g.putcells(addition,0,1)
g.setname('Solution')
You can make it a lot faster by getting rid of the addlayer / dellayer again and extracting the line you're interested in, directly from the evolved cell list -- it's actually going to be the slice of that list, evolved[i:j], where the y value matches the iteration number.
And yes, that was exactly the intended behaviour!

It's quite frustrating for me to be unable to code even simple stuff like this... I guess it's a matter of practice and finding online resources to get more information.
Thank you for your help! (not only for the code itself but to help me realise where my mistakes were!)
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Help with my scripts

Post by Rhombic » December 1st, 2017, 9:01 am

A bit of a change of scene now that I feel very comfortable with Python...now my issues involve C.

Code: Select all

#include <stdio.h>

int factorial(int n){
	int nN; int i;
	for(i=0;i<n;i++){
		nN=1;
		nN*=(n-i+1);
	}
	return nN;
}
int power(int b, int exp){
	int bB; int i;
	for(i=0;i<exp;i++){
		bB=1;
		bB*=b;
	}
	return bB;
}
int main(){
	printf("Showing the minimum n for which A^n > A! \n A \t n");
	int i;
	for(i=1;factorial(i)<1000000000;i++){
		int c; c=1;
		while (c>0){
			if (power(i,c)>factorial(i)){
				printf("%d \t %d",i,c);
				break;
			}
			c++;
		}
	}
	return 0;
}
The script is fairly simple. For integer A, it gives the smallest integer n so that A^n > A!. It doesn't work and, unlike Python, C doesn't really help you much with the debugging. How can I find the issue?
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

Post Reply