For scripts to aid with computation or simulation in cellular automata.

danny wrote:...I'm wondering if there's anything I could optimize besides the 'if str(x).find("0") == -1 and str(y).find("0") == -1:' line.

Sure, I can think of a few things, and I'm sure other people can come up with more.

First, you're doing the str(x) and str(y) conversions twice each, and it's easy to cut that in half by changing how you're doing the iteration. Probably something like this would be a little faster, but you'd have to do some speed trials to see how much:

    for i in str(x):      cx *= int(i)    for i in str(y):      cy *= int(i)

Then, an even less consequential improvement, you might possibly shave some tiny fractional seconds off with the right kind of lookup table. A dictionary might be the best:

lookup=dict()for i in "0123456789":  lookup[i]=int(i)

Or you could try a simple list, and the ASCII value of each character:
lookup=[0]*256for i in "123456789":  lookup[ord(i)]=int(i)

But then you'd need to use cx *= lookup[ord(i)] instead of just cx *= lookup[i], so again you'd have to run time trials to see which is better.

Or again, try doing everything numerically instead of converting to a string -- like
k=xwhile k>0:  digit=k%10  k-=digit  k/=10  # multiply cx by digit, etc.

String really are pretty slow sometimes compared to numeric calculations -- but I don't know if this is one of those times or not.

dvgrn
Moderator

Posts: 5621
Joined: May 17th, 2009, 11:00 pm

An update! I did something pretty clever, I removed the 'if str' statement and appended this at the end of the loop:
  while "0" in str(x):    x += 10 ** (len(str(x)) - str(x).find("0") - 1)

Overall it's still shorter due to the if statement being removed, in favour of this faster alternative, as well as faster because it doesn't waste time counting like 5000000...5000001...5000002, it goes 5000000...5111111...5111112

EDIT: replaced 'str(x).find("0") != -1' with 'while "0" in str(x)' as of M.I. Wright's request
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.

danny

Posts: 944
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

Hey, I'm having trouble with this:
# powerz.py v1.99# danny c, 2018# checks what number x gives when you multiply its digits, then compares it against what it gives when you multiply its square's digits. if they are equal, it prints and writes to results.txt (check that file for my search progress! <3)# also special thanks to @schimatt for pretty much all of this, and helping me learn python in general c:# this was my first real python scriptwith open("powerz_results.txt", "r") as res:  x = int((list(res)[-1])) + 1  num_res = sum(1 for line in open("powerz_results.txt"))  print("last result:", x - 1,"is applicable. (#" + str(num_res) + ")")# x = 0while True:  y = x ** 2  cx = 1  cy = 1  for i in str(x):    cx *= int(i)  for i in str(y):    cy *= int(i)  if cx == cy:    num_res += 1    print(str(x) + " is applicable. (#" + str(num_res) + ", " + str(cx) + "==" + str(cy) + ")")    with open("powerz_results.txt", "a") as res:      res.write("\n" + str(x))  x += 1  while "0" in str(x):    x += 10 ** (len(str(x)) - str(x).find("0") - 1)    # print(x)

For example, with the number 53489358889, it counts by:
last result: 53489358889 is applicable. (#1)53489358890 is applicable. (#2, 0==0)53489358910534893589115348935892153489358931534893589415348935895153489358961534893589715348935898153489358991534893591005348935911053489359111

Note the false positive 53489358890, and the fact that it counts by 10's when there are no 0's. It was working fine earlier, what gives?

EDIT: Oh, I'm stupid I set it only to print after incrementing by 10s, so it's working correctly. Disregard this post.
EDIT2: Added another loop to skip everything else if 0 in x ** 2.
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.

danny

Posts: 944
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

If I've generated long binary strings that equate to initial conditions for Wolfram Rule 110, is there a script out there that can convert this to an RLE or MC? Basically just translating a long binary string into a long line of on/off cells.

thorsilver

Posts: 13
Joined: March 31st, 2018, 9:43 pm
Location: Glasgow, Scotland

thorsilver wrote:If I've generated long binary strings that equate to initial conditions for Wolfram Rule 110, is there a script out there that can convert this to an RLE or MC? Basically just translating a long binary string into a long line of on/off cells.

test it pls, might be buggy - in perl. I can rewrite it in any lang. like bash/ksh/sh, python etc:

user@errorlevel:0:~$echo ooooooobbbbbbbbbobobbbbbb | perl -pe 's((([ob])\2+))(length($1).$2)eg'7o9bobo6b Naszvadi Posts: 346 Joined: May 7th, 2016, 8:53 am ### Re: Script request thread Naszvadi wrote: thorsilver wrote:If I've generated long binary strings that equate to initial conditions for Wolfram Rule 110, is there a script out there that can convert this to an RLE or MC? Basically just translating a long binary string into a long line of on/off cells. test it pls, might be buggy - in perl. I can rewrite it in any lang. like bash/ksh/sh, python etc: user@errorlevel:0:~$ echo ooooooobbbbbbbbbobobbbbbb | perl -pe 's((([ob])\2+))(length($1).$2)eg'7o9bobo6b

Thanks for this -- sadly I can't get it to work, I know nothing at all about Perl

Any chance of a version in Python?

thorsilver

Posts: 13
Joined: March 31st, 2018, 9:43 pm
Location: Glasgow, Scotland

thorsilver wrote:
thorsilver wrote:If I've generated long binary strings that equate to initial conditions for Wolfram Rule 110, is there a script out there that can convert this to an RLE or MC? Basically just translating a long binary string into a long line of on/off cells.

test it pls, might be buggy - in perl. I can rewrite it in any lang. like bash/ksh/sh, python etc:

user@errorlevel:0:~$echo ooooooobbbbbbbbbobobbbbbb | perl -pe 's((([ob])\2+))(length($1).$2)eg'7o9bobo6b Thanks for this -- sadly I can't get it to work, I know nothing at all about Perl Any chance of a version in Python? Here you are: # mandatory beginimport re# mandatory end# example variablea='bbbbbbbboooooooooobobbbbbbbbbobbbbbbbb'# mandatory begindef squeezerepl(matchobj): return (str(len(matchobj.group(0))) + matchobj.group(0)[0])# mandatory endprint "### DEBUG ### original a = '%s'" % (a)# mandatory beginb = re.sub(r'(([bo])\2+)', squeezerepl, a)# mandatory endprint "### DEBUG ### modified a = '%s'" % (b) Naszvadi Posts: 346 Joined: May 7th, 2016, 8:53 am ### Re: Script request thread Naszvadi wrote: thorsilver wrote:Any chance of a version in Python? Here you are... ... a='bbbbbbbboooooooooobobbbbbbbbbobbbbbbbb' ... Once you have the string in that form with b's and o's, it's perfectly valid RLE already. Here's a "Golly Python" implementation starting from a standard binary string like '00000000111111111101000000000100000000'. It might do slightly odd things if you have characters other than 0s and 1s in the input string, but Golly usually just tries to ignore non-standard characters so it will usually come out okay. Just copy the script below and choose File > Run Clipboard in Golly: import golly as ga=g.getstring("Enter binary string for W110 initial conditions: ")if len(a): g.new("W110") # or g.addlayer() if you don't want to overwrite the current layer's pattern g.setrule("W110") g.select([0,0,len(a),1]) g.putcells(g.parse(a.replace("0","b").replace("1","o"))) g.fit() If you want to get RLE back out again as a string in canonical form, you could add another line to save the file:  g.save("C:/Temp/W110initial.rle","rle") -- or modify Naszvadi's script, if you're just converting and storing lots of RLE strings and don't want to use Golly to simulate the patterns. dvgrn Moderator Posts: 5621 Joined: May 17th, 2009, 11:00 pm Location: Madison, WI ### Re: Script request thread Thanks folks! Apologies for my cluelessness about RLE files. In the end I combined inspiration from both of your scripts. I found that both the g.getstring() and g.getclipstr() top out at about 125,000 characters, so I had to get something working on the command line. Then I found that I needed the RLE to constrain the width of the pattern, otherwise the left edge would expand and fire gliders off to the right, which would totally muck up the cyclic tag system implementations I was hoping to simulate with this! So I fixed that and messed around a bit and this is the result: with open('initial_conditions.txt', 'r') as myfile: a=myfile.read()b = a.replace("1", "o").replace("0", "b")x = len(a)with open("W110 initial conditions.rle", "w") as text_file: text_file.write("x = 0, y = 0, rule = W110:T{},0\n".format(x)) text_file.write(b) It takes a text file of binary digits and outputs an RLE that loads into Golly correctly, loads the W110 rule and constrains the pattern width to avoid spurious gliders. Perfect! Thank you both again! As a bonus I've attached a W110 cyclic tag system pattern that this script just produced. This is a CTS taken from Wolfram's book which is defined by this rule: [{{1, 1, 0, 1, 0, 1}, {1, 1, 0, 0, 0, 0}}, {0, 1}]. The left side of the pattern is sparse, with just a few packs of gliders set up to modify the data which is a series of vertical gliders in the middle, with other gliders defining the CTS rule on the right side of the pattern. This simple CTS takes up 219,205 cells! Of course I also generated a W110 unit cell version that runs in GoL -- I'll put that in my thread on W110 unit cell patterns in the Patterns forum, in case anyone wants to see it. EDIT: Made a slight tweak to the script, so if you generate a W110 Cyclic Tag System initial condition in Mathematica as I did, you can save that output in a text file called 'initial_conditions_W110.txt' and run the script below in the same folder to generate an RLE for the corresponding W110 pattern. It's very quick-and-dirty and could be cleaned up a bunch, but it works. Made a different script as well that generates W110 unit cell patterns directly from the same Mathematica output, which I posted in the other thread. import rewith open('initial_conditions_W110.txt', 'r') as myfile: a=myfile.read()b = re.sub('[{,} ]', '', a)b = b.replace('\r', '')b = a.replace("1", "o").replace("0", "b")x = len(a)with open("W110 initial conditions.rle", "w") as text_file: text_file.write("x = 0, y = 0, rule = W110:T{},0\n".format(x)) text_file.write(b) Attachments W110 initial conditions CTS 1.rle (214.1 KiB) Downloaded 145 times thorsilver Posts: 13 Joined: March 31st, 2018, 9:43 pm Location: Glasgow, Scotland ### Re: Script request thread Hi! I'm looking for some help on this: def isprime(m): # UGLY LOOP SANDWICH INCOMING prime = True for i in range(2, int(m ** .5) + 1): if m % i == 0: prime = i break return primen = 3 # NUMBER YOU WANT TO TESTm = 50 # EXPONENT BEING USED# ...isprime(n ** m - (2 ** m - 1)) # basically just 3 ** 50 It returns a float error, for being too large. How can I remedy this? Can I remedy this? I've tried using Decimal, but not numpy yet. Does numpy work with big numbers like this? she/they // Please stop using my full name. Refer to me as dani. "I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D. danny Posts: 944 Joined: October 27th, 2017, 3:43 pm Location: New Jersey, USA ### Re: Script request thread danny wrote:Hi! I'm looking for some help on this: def isprime(m): # UGLY LOOP SANDWICH INCOMING prime = True for i in range(2, int(m ** .5) + 1): if m % i == 0: prime = i break return primen = 3 # NUMBER YOU WANT TO TESTm = 50 # EXPONENT BEING USED# ...isprime(n ** m - (2 ** m - 1)) # basically just 3 ** 50 It returns a float error, for being too large. How can I remedy this? Can I remedy this? I've tried using Decimal, but not numpy yet. Does numpy work with big numbers like this? I'm not sure, but I suspect the range function can't handle numbers larger than 2^64 for whatever reason. Replacing the for loop with a while loop works for me, and gives a dramatic speedup to boot: def isprime(m): # UGLY BLM (BOOLEAN OPERATOR, LOOP, AND MATH) SANDWICH INCOMING q = int(m ** .5) + 1 i = 2 while i < q and m % i: i += 1 return i == q or in = 3 # NUMBER YOU WANT TO TESTm = 50 # EXPONENT BEING USED# ...isprime(n ** m - (2 ** m - 1)) # basically just 3 ** 50 Obviously there are much faster primality testing algorithms out there, most of which I've probably never heard of. Also, for odd n the number you're testing will always be composite, since n^m-2^m+1 is always divisible by 2 for odd m. x₁=ηx V ⃰_η=c²√(Λη) K=(Λu²)/2 Pₐ=1−1/(∫^∞_t₀(p(t)ˡ⁽ᵗ⁾)dt) $$x_1=\eta x$$ $$V^*_\eta=c^2\sqrt{\Lambda\eta}$$ $$K=\frac{\Lambda u^2}2$$ $$P_a=1-\frac1{\int^\infty_{t_0}p(t)^{l(t)}dt}$$ http://conwaylife.com/wiki/A_for_all Aidan F. Pierce A for awesome Posts: 1807 Joined: September 13th, 2014, 5:36 pm Location: 0x-1 ### Re: Script request thread Thanks for that, although I should have clarified that this is the error I'm getting:  File "D:\Users\Dan\Desktop\python\pricol.py", line 6, in isprime q = int(m ** .5) + 1OverflowError: int too large to convert to float she/they // Please stop using my full name. Refer to me as dani. "I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D. danny Posts: 944 Joined: October 27th, 2017, 3:43 pm Location: New Jersey, USA ### Re: Script request thread If it's too large to convert to a float, you want to be using Miller-Rabin (or AKS, but that's slower and harder) for primality testing. What do you do with ill crystallographers? Take them to the mono-clinic! calcyman Posts: 2025 Joined: June 1st, 2009, 4:32 pm ### Re: Script request thread calcyman wrote:If it's too large to convert to a float, you want to be using Miller-Rabin (or AKS, but that's slower and harder) for primality testing. To clarify -- one of the biggest reasons why you want to use something other than the naive prime-testing algorithm is that you can't possibly run a Python for loop from 2 even as far as 10^19 in practice, let alone 10^38, even if the conversion worked. 9223372036854775807, about 10^19, is I think the maximum 64-bit integer that Python can store. Depending on the Python version, you might be able to get silent conversion to long or arbitrary precision ints, or you could use Decimal or some other arbitrary-precision type. But there's really no point because 10^19 is already too big. (-- Yes, I use Golly as my experimental IDE...) import golly as gimport times = time.time()prime = Truemaximumint = 9223372036854775807m=99999999977for i in xrange(3,10**8,2): if m % i == 0: prime = i break# if i%10000==1: g.show(str(i))g.note("Prime-testing maximumint will take " + str((time.time()-s)*10**11/60/60/24/365)+" years, give or take a few.") On my system, according to the above Ultra Scientfic Test Script, testing even a small number like 9223372036854775807 for primality will take just under 30,000 years. If you don't change "range" to "xrange" in Python 2, by the way, the script will never even get started, and it's worth looking up and understanding the reason why. Basically range builds a list of all the numbers in the range before it starts... Python 3 isn't that silly -- range in Python 3 is the same as xrange in Python 2. dvgrn Moderator Posts: 5621 Joined: May 17th, 2009, 11:00 pm Location: Madison, WI ### Re: Script request thread Can I have some pointers on computing these numbers? A partial script would be nice, but I only really need pointers on how to do a brute force script she/they // Please stop using my full name. Refer to me as dani. "I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D. danny Posts: 944 Joined: October 27th, 2017, 3:43 pm Location: New Jersey, USA ### Re: Script request thread Okay, this time I've computed everything pretty much right, but the problem is that it balloons to 1.6 GB of RAM for some reason. Can I fix this in any way or should I just choose a different algorithm?: # CALCULATES THE SUNRISE SEQUENCE FOR N# VERY MESSYfrom sympy.ntheory import factorintimport operatorm = 12def readable(n): # changes script output # get all your ducks in a row # organize factors in order least to greatest to improve readability n = sorted(n.items(), key=operator.itemgetter(0)) n = str(n) # replacements for output n = n.replace(", 1","") n = n.replace("), ("," * ") n = n.replace("[","") n = n.replace("]","") n = n.replace("(","") n = n.replace(")","") n = n.replace(", ","^") return ndef nextterm(n): # very nice method from my flamingo.py on repl.it y = "" n = str(n) for i in range(0,10): for j in range(0,n.count(str(9 - i))): y += str(9 - i) return ywhile True: z = readable(factorint(int(m))) print(str(m) + " = " + z) with open("sunres.txt","a+") as sunres: sunres.write(str(m) + " " + z + "\n") m = nextterm(z) Apologies for future posters for turning this into script help thread, but it hasn't seen much use... she/they // Please stop using my full name. Refer to me as dani. "I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D. danny Posts: 944 Joined: October 27th, 2017, 3:43 pm Location: New Jersey, USA ### Re: Script request thread Can anyone make me a script that rotates JvN patters, arrows included? KittyTac Posts: 533 Joined: December 21st, 2017, 9:58 am ### Re: Script request thread And also flip them (even though it changes the behaviour, just do it) c(>^w^<c)~* This is Fluffy the cat. Fluffy wants to discover new things that everyone likes. Fluffy thinks about engineering replicators. Fluffy likes to watch spaceship guns in Golly. Fluffy knows Natsuki best girl. Redstoneboi Posts: 335 Joined: May 14th, 2018, 3:57 am ### Re: Script request thread Redstoneboi wrote:And also flip them (even though it changes the behaviour, just do it) I don't think that Hutton32 patterns would change behavior when rotated. And Hutton32 is the superior one anyways. KittyTac Posts: 533 Joined: December 21st, 2017, 9:58 am ### Re: Script request thread dvgrn wrote:Maybe a script would be a good idea: when run in Golly when the current universe is a two-state isotropic rule on a bounded P{x,y} grid, the script could generate the equivalent custom rule with an extra "permanent dead" state, and line an (x,y) rectangle with those cells. I misinterpreted what you were looking for because of the context in which it was asked. But I thought this was a nice idea anyway, so here is iso-permaOn-gen.py It's a bit of a hack based on isotropic-rule.py and as such the comments are a bit dodgy and sparse. It generates a 3 state rule with permaOn cells and then optionally draws a boundary of permaOn cells on the border of a bounded grid. # iso-permaOn-gen.py## Derived from isotropic-rule.py / isotropicRulegen.py # which itself was derived from apgsearch v1.0# # Generate a rule table for an isotropic rule using Alan Hensel's# isotropic, non-totalistic rule format for CA on the Moore neighbourhood# Adds a third state representing permanently On cells# # Includes code written by: Eric Goldstein, Adam P. Goucher, Dave Green, Arie Paap, and Andrew Trevorrowimport golly as gimport os# Generates the helper rules for apgsearch-isotropic, given a base isotropic# rule in Hensel's notation.class RuleGenerator: # notationdict adapted from Eric Goldstein's HenselNotation->Ruletable(1.3).py # Modified for neighbourhood2 version of Hensel's notation notationdict = { "0" : [0,0,0,0,0,0,0,0], # "1e" : [1,0,0,0,0,0,0,0], # N "1c" : [0,1,0,0,0,0,0,0], # NE "2a" : [1,1,0,0,0,0,0,0], # N, NE "2e" : [1,0,1,0,0,0,0,0], # N, E "2k" : [1,0,0,1,0,0,0,0], # N, SE "2i" : [1,0,0,0,1,0,0,0], # N, S "2c" : [0,1,0,1,0,0,0,0], # NE, SE "2n" : [0,1,0,0,0,1,0,0], # NE, SW "3a" : [1,1,1,0,0,0,0,0], # N, NE, E "3n" : [1,1,0,1,0,0,0,0], # N, NE, SE "3r" : [1,1,0,0,1,0,0,0], # N, NE, S "3q" : [1,1,0,0,0,1,0,0], # N, NE, SW "3j" : [1,1,0,0,0,0,1,0], # N, NE, W "3i" : [1,1,0,0,0,0,0,1], # N, NE, NW "3e" : [1,0,1,0,1,0,0,0], # N, E, S "3k" : [1,0,1,0,0,1,0,0], # N, E, SW "3y" : [1,0,0,1,0,1,0,0], # N, SE, SW "3c" : [0,1,0,1,0,1,0,0], # NE, SE, SW "4a" : [1,1,1,1,0,0,0,0], # N, NE, E, SE "4r" : [1,1,1,0,1,0,0,0], # N, NE, E, S "4q" : [1,1,1,0,0,1,0,0], # N, NE, E, SW "4i" : [1,1,0,1,1,0,0,0], # N, NE, SE, S "4y" : [1,1,0,1,0,1,0,0], # N, NE, SE, SW "4k" : [1,1,0,1,0,0,1,0], # N, NE, SE, W "4n" : [1,1,0,1,0,0,0,1], # N, NE, SE, NW "4z" : [1,1,0,0,1,1,0,0], # N, NE, S, SW "4j" : [1,1,0,0,1,0,1,0], # N, NE, S, W "4t" : [1,1,0,0,1,0,0,1], # N, NE, S, NW "4w" : [1,1,0,0,0,1,1,0], # N, NE, SW, W "4e" : [1,0,1,0,1,0,1,0], # N, E, S, W "4c" : [0,1,0,1,0,1,0,1], # NE, SE, SW, NW "5i" : [1,1,1,1,1,0,0,0], # N, NE, E, SE, S "5j" : [1,1,1,1,0,1,0,0], # N, NE, E, SE, SW "5n" : [1,1,1,1,0,0,1,0], # N, NE, E, SE, W "5a" : [1,1,1,1,0,0,0,1], # N, NE, E, SE, NW "5q" : [1,1,1,0,1,1,0,0], # N, NE, E, S, SW "5c" : [1,1,1,0,1,0,1,0], # N, NE, E, S, W "5r" : [1,1,0,1,1,1,0,0], # N, NE, SE, S, SW "5y" : [1,1,0,1,1,0,1,0], # N, NE, SE, S, W "5k" : [1,1,0,1,0,1,1,0], # N, NE, SE, SW, W "5e" : [1,1,0,1,0,1,0,1], # N, NE, SE, SW, NW "6a" : [1,1,1,1,1,1,0,0], # N, NE, E, SE, S, SW "6c" : [1,1,1,1,1,0,1,0], # N, NE, E, SE, S, W "6k" : [1,1,1,1,0,1,1,0], # N, NE, E, SE, SW, W "6e" : [1,1,1,1,0,1,0,1], # N, NE, E, SE, SW, NW "6n" : [1,1,1,0,1,1,1,0], # N, NE, E, S, SW, W "6i" : [1,1,0,1,1,1,0,1], # N, NE, SE, S, SW, NW "7c" : [1,1,1,1,1,1,1,0], # N, NE, E, SE, S, SW, W "7e" : [1,1,1,1,1,1,0,1], # N, NE, E, SE, S, SW, NW "8" : [1,1,1,1,1,1,1,1], # N, NE, E, SE, S, SW, W, NW } allneighbours = [ ["0"], ["1e", "1c"], ["2a", "2e", "2k", "2i", "2c", "2n"], ["3a", "3n", "3r", "3q", "3j", "3i", "3e", "3k", "3y", "3c"], ["4a", "4r", "4q", "4i", "4y", "4k", "4n", "4z", "4j", "4t", "4w", "4e", "4c"], ["5i", "5j", "5n", "5a", "5q", "5c", "5r", "5y", "5k", "5e"], ["6a", "6c", "6k", "6e", "6n", "6i"], ["7c", "7e"], ["8"], ] allneighbours_flat = [n for x in allneighbours for n in x] numneighbours = len(notationdict) # Use dict to store rule elements, initialised by setrule(): bee = {} ess = {} alphanumeric = "" rulename = "" # Save the isotropic rule def saveAllRules(self): self.saveIsotropicRule() # Interpret birth or survival string def ruleparts(self, part): inverse = False nlist = [] totalistic = True rule = { k: False for k, v in self.notationdict.iteritems() } # Reverse the rule string to simplify processing part = part[::-1] for c in part: if c.isdigit(): d = int(c) if totalistic: # Add all the neighbourhoods for this value for neighbour in self.allneighbours[d]: rule[neighbour] = True elif inverse: # Add all the neighbourhoods not in nlist for this value for neighbour in self.allneighbours[d]: if neighbour[1] not in nlist: rule[neighbour] = True else: # Add all the neighbourhoods in nlist for this value for n in nlist: neighbour = c + n if neighbour in rule: rule[neighbour] = True else: # Error return {} inverse = False nlist = [] totalistic = True elif (c == '-'): inverse = True else: totalistic = False nlist.append(c) return rule # Set isotropic, non-totalistic rule # Adapted from Eric Goldstein's HenselNotation->Ruletable(1.3).py def setrule(self, rulestring): # neighbours_flat = [n for x in neighbours for n in x] b = {} s = {} sep = '' birth = '' survive = '' rulestring = rulestring.lower() if '/' in rulestring: sep = '/' elif '_' in rulestring: sep = '_' elif (rulestring[0] == 'b'): sep = 's' else: sep = 'b' survive, birth = rulestring.split(sep) if (survive[0] == 'b'): survive, birth = birth, survive survive = survive.replace('s', '') birth = birth.replace('b', '') b = self.ruleparts(birth) s = self.ruleparts(survive) if b and s: self.alphanumeric = 'B' + birth + 'S' + survive self.rulename = 'B' + birth + 'S' + survive self.bee = b self.ess = s else: # Error g.note("Unable to process rule definition.\n" + "b = " + str(b) + "\ns = " + str(s)) g.exit() # Save a rule file: def saverule(self, name, comments, table, colours): ruledir = g.getdir("rules") filename = ruledir + name + ".rule" results = "@RULE " + name + "\n\n" results += "*** File autogenerated by saverule. ***\n\n" results += comments results += "\n\n@TABLE\n\n" results += table results += "\n\n@COLORS\n\n" results += colours results += "\n\n@ICONS\n\n" results += "circles\n" try: f = open(filename, 'w') f.write(results) f.close() except: g.warn("Unable to create rule table:\n" + filename) # Defines a variable: def newvar(self, name, vallist): line = "var "+name+"={" for i in xrange(len(vallist)): if (i > 0): line += ',' line += str(vallist[i]) line += "}\n" return line # Defines a block of equivalent variables: def newvars(self, namelist, vallist): block = "\n" for name in namelist: block += self.newvar(name, vallist) return block def scoline(self, chara, charb, left, right, amount): line = str(left) + "," for i in xrange(8): if (i < amount): line += chara else: line += charb line += chr(97 + i) line += "," line += str(right) + "\n" return line def isotropicline(self, chara, charb, left, right, n): line = str(left) + "," neighbours = self.notationdict[n] for i in xrange(8): if neighbours[i]: line += chara else: line += charb line += chr(97 + i) line += "," line += str(right) + "\n" return line def savePermaOnRule(self): comments = """This is a two state, isotropic, non-totalistic rule on the Moore neighbourhood.This rules add a third state which acts as a permanently On cell.""" table = """n_states:3neighborhood:Mooresymmetries:rotate4reflect""" table += self.newvars(["a","b","c","d","e","f","g","h"], [0, 1, 2]) table += self.newvars(["da","db","dc","dd","de","df","dg","dh"], [0]) table += self.newvars(["la","lb","lc","ld","le","lf","lg","lh"], [1, 2]) table += "\n# Birth\n" for n in self.allneighbours_flat: if self.bee[n]: table += self.isotropicline('l', 'd', 0, 1, n) table += "\n# Survival\n" for n in self.allneighbours_flat: if self.ess[n]: table += self.isotropicline('l', 'd', 1, 1, n) table += "\n# Death\n" table += self.scoline("","",1,0,0) colours = """1 255 0 02 0 64 255""" self.saverule(self.rulename, comments, table, colours)# Adapted from Golly's draw-lines.py by Andrew Trevorrowdef drawline(x1, y1, x2, y2, drawstate): # draw a line of cells from x1,y1 to x2,y2 using Bresenham's algorithm; if x1 == x2 and y1 == y2: return dx = x2 - x1 ax = abs(dx) * 2 sx = 1 if dx < 0: sx = -1 dy = y2 - y1 ay = abs(dy) * 2 sy = 1 if dy < 0: sy = -1 if ax > ay: d = ay - (ax / 2) while x1 != x2: g.setcell(x1, y1, drawstate) if d >= 0: y1 += sy d -= ax x1 += 2*sx d += ay else: d = ax - (ay / 2) while y1 != y2: g.setcell(x1, y1, drawstate) if d >= 0: x1 += sx d -= ay y1 += 2*sy d += ax g.setcell(x2, y2, drawstate) return# Test the current rule to see if it can be usedbounds = ''if g.getalgo() in ['QuickLife', 'HashLife']: rulestring = g.getrule() if ':' in rulestring: rulestring, bounds = rulestring.split(':')else: rulestring = 'B3S23' rulestring = g.getstring("This script generates a rule table for an isotropic 2-state CA\n" + "with an added third state which act as permanently On cells\n" + "Enter rule string in Alan Hensel's isotropic rule notation", rulestring)rg = RuleGenerator()rg.setrule(rulestring)rg.rulename = "PermaOn_" + rg.rulenamerg.savePermaOnRule()if bounds and (bounds[0] == 'P'): wd, ht = map(int, bounds[1:].split(',')) g.show(str([wd,ht]))else: size = g.getstring("Enter size of bounded grid to create, 0 to skip:", "0") try: wd = int(size) ht = wd except: wd, ht = 0, 0if wd and ht: g.setrule("%s:P%d,%d" % (rg.rulename, wd, ht)) # Draw a boundary of PermaOn cells left, right, top, bottom = -wd/2+wd%2, wd/2-1+wd%2, -ht/2+ht%2, ht/2-1+ht%2 drawline(left, top, right, top, 2) drawline(right, top, right, bottom, 2) drawline(right, bottom, left, bottom, 2) drawline(left, bottom, left, top, 2)else: g.setrule(rg.rulename) To modify this to get the originally requested script would probably only require a few changes: In savePermOnRule(), change  table += self.newvars(["da","db","dc","dd","de","df","dg","dh"], [0]) table += self.newvars(["la","lb","lc","ld","le","lf","lg","lh"], [1, 2]) to  table += self.newvars(["da","db","dc","dd","de","df","dg","dh"], [0, 2]) table += self.newvars(["la","lb","lc","ld","le","lf","lg","lh"], [1]) and where the boundary is drawn, change  g.setrule("%s:P%d,%d" % (rg.rulename, wd, ht)) to  g.setrule(rg.rulename) wd = wd + 2 ht = ht + 2 Some comments and other bits of text should also be updated if it were to be published, and then I realised it made more sense for the script to create a four state rule with both permaOn and permaOff cells. Then one script could simulate bounded grids with outer space being wither all On cells or all Off cells without needing a bounded grid in Golly. The latest version of the 5S Project contains over 47,000 spaceships. Tabulated pages up to period 160 are available on the LifeWiki. wildmyron Posts: 1110 Joined: August 9th, 2013, 12:45 am ### Re: Script request thread How about an Energetic-izer script? (Energetic is a rule in the rule request thread). Basically, this script takes any Hensel-notation rule and makes an Energetic rule out of it, with two states of the Hensel rule and with normal energy states. Can you make it? KittyTac Posts: 533 Joined: December 21st, 2017, 9:58 am ### Re: Script request thread KittyTac wrote:Can you make it? Was that directed at me? Copying my response from PM It's doable, but introduces a lot more complexity in the matter / antimatter interactions. I would probably use a rule generator to create the isotropic lines for matter and antimatter in nutshell format, and then combine it with the annihilation + photon generation + photon movement which would be fixed. I really don't fancy working out how to write all the rules for matter/antimatter interaction though. Also, the photon interaction isn't complete yet as there are still asymmetries there. I'm afraid this is not a project I can take on now. If no-one else picks it up I may have a go in a month or so, but I've already got a backlog of unfinished projects so I don't want to add another to the list. The latest version of the 5S Project contains over 47,000 spaceships. Tabulated pages up to period 160 are available on the LifeWiki. wildmyron Posts: 1110 Joined: August 9th, 2013, 12:45 am ### Re: Script request thread I guess someone else can make it. KittyTac Posts: 533 Joined: December 21st, 2017, 9:58 am ### Re: Script request thread I would like a script that searches for a glider synthesis for a given input pattern, to try to find a synthesis for Sir Robin. EDIT: Such a script should also output the synthesis, if one is found. Last edited by Gamedziner on September 27th, 2018, 1:07 pm, edited 1 time in total. x = 81, y = 96, rule = LifeHistory58.2A$58.2A3$59.2A17.2A$59.2A17.2A3$79.2A$79.2A2$57.A$56.A$56.3A4$27.A$27.A.A$27.2A21$3.2A$3.2A2.2A$7.2A18$7.2A$7.2A2.2A$11.2A11$2A$2A2.2A$4.2A18$4.2A$4.2A2.2A$8.2A!
Gamedziner

Posts: 709
Joined: May 30th, 2016, 8:47 pm
Location: Milky Way Galaxy: Planet Earth

Gamedziner wrote:I would like a script that searches for a glider synthesis for a given input pattern, to try to find a synthesis for Sir Robin.

So would I. Actually, I'd like a script that actually finds a synthesis, rather than just searching for it. While I'm wishing, I'd like it to be guaranteed that the synthesis is the most efficient one possible.

dvgrn
Moderator

Posts: 5621
Joined: May 17th, 2009, 11:00 pm