For scripts to aid with computation or simulation in cellular automata.
dvgrn
Moderator
Posts: 6710
Joined: May 17th, 2009, 11:00 pm
Contact:

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:

Code: Select all

    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:

Code: Select all

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

Or you could try a simple list, and the ASCII value of each character:

Code: Select all

lookup=[0]*256
for i in "123456789":
lookup[ord(i)]=int(i)
But then you'd need to use cx *= lookup[ord(i)] instead of just cx *= lookup, 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

Code: Select all

k=x
while 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.

dani
Posts: 1002
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA
Contact:

An update! I did something pretty clever, I removed the 'if str' statement and appended this at the end of the loop:

Code: Select all

  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/her
moose#0915

dani
Posts: 1002
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA
Contact:

Hey, I'm having trouble with this:

Code: Select all

# 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 script
with 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 = 0
while 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:

Code: Select all

last result: 53489358889 is applicable. (#1)
53489358890 is applicable. (#2, 0==0)
53489358910
53489358911
53489358921
53489358931
53489358941
53489358951
53489358961
53489358971
53489358981
53489358991
53489359100
53489359110
53489359111
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/her
moose#0915

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

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.

Posts: 571
Joined: May 7th, 2016, 8:53 am
Contact:

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:

Code: Select all

user@errorlevel:0:~$echo ooooooobbbbbbbbbobobbbbbb | perl -pe 's((([ob])\2+))(length($1).$2)eg' 7o9bobo6b  thorsilver Posts: 13 Joined: March 31st, 2018, 9:43 pm Location: Glasgow, Scotland 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: Code: Select all 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?

Posts: 571
Joined: May 7th, 2016, 8:53 am
Contact:

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:

Code: Select all

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: Code: Select all # mandatory begin import re # mandatory end # example variable a='bbbbbbbboooooooooobobbbbbbbbbobbbbbbbb' # mandatory begin def squeezerepl(matchobj): return (str(len(matchobj.group(0))) + matchobj.group(0)[0]) # mandatory end print "### DEBUG ### original a = '%s'" % (a) # mandatory begin b = re.sub(r'(([bo])\2+)', squeezerepl, a) # mandatory end print "### DEBUG ### modified a = '%s'" % (b)  dvgrn Moderator Posts: 6710 Joined: May 17th, 2009, 11:00 pm Location: Madison, WI Contact: 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: Code: Select all import golly as g a=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: Code: Select all  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. thorsilver Posts: 13 Joined: March 31st, 2018, 9:43 pm Location: Glasgow, Scotland 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: Code: Select all 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. Code: Select all import re with 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 178 times dani Posts: 1002 Joined: October 27th, 2017, 3:43 pm Location: New Jersey, USA Contact: Re: Script request thread Hi! I'm looking for some help on this: Code: Select all 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 prime n = 3 # NUMBER YOU WANT TO TEST m = 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/her moose#0915 A for awesome Posts: 2036 Joined: September 13th, 2014, 5:36 pm Location: 0x-1 Contact: Re: Script request thread dani wrote:Hi! I'm looking for some help on this: Code: Select all 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 prime n = 3 # NUMBER YOU WANT TO TEST m = 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: Code: Select all 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 i n = 3 # NUMBER YOU WANT TO TEST m = 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. Last edited by A for awesome on April 23rd, 2020, 1:20 am, edited 1 time in total. 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 dani Posts: 1002 Joined: October 27th, 2017, 3:43 pm Location: New Jersey, USA Contact: Re: Script request thread Thanks for that, although I should have clarified that this is the error I'm getting: Code: Select all  File "D:\Users\Dan\Desktop\python\pricol.py", line 6, in isprime q = int(m ** .5) + 1 OverflowError: int too large to convert to float she/her moose#0915 calcyman Posts: 2198 Joined: June 1st, 2009, 4:32 pm 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! dvgrn Moderator Posts: 6710 Joined: May 17th, 2009, 11:00 pm Location: Madison, WI Contact: 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...) Code: Select all import golly as g import time s = time.time() prime = True maximumint = 9223372036854775807 m=99999999977 for 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. dani Posts: 1002 Joined: October 27th, 2017, 3:43 pm Location: New Jersey, USA Contact: 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/her moose#0915 dani Posts: 1002 Joined: October 27th, 2017, 3:43 pm Location: New Jersey, USA Contact: 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?: Code: Select all # CALCULATES THE SUNRISE SEQUENCE FOR N # VERY MESSY from sympy.ntheory import factorint import operator m = 12 def 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 n def 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 y while 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/her moose#0915 KittyTac Posts: 533 Joined: December 21st, 2017, 9:58 am Re: Script request thread Can anyone make me a script that rotates JvN patters, arrows included? Redstoneboi Posts: 370 Joined: May 14th, 2018, 3:57 am Re: Script request thread And also flip them (even though it changes the behaviour, just do it) c(>^w^<c)~* This is 「Fluffy」 「Fluffy」is my sutando. 「Fluffy」has the ability to engineer r e p l i c a t o r s. 「Fluffy」likes to watch spaceship guns in Golly. 「Fluffy」knows Natsuki best girl. KittyTac Posts: 533 Joined: December 21st, 2017, 9:58 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. wildmyron Posts: 1397 Joined: August 9th, 2013, 12:45 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. Code: Select all # 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 Trevorrow import golly as g import 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:3 neighborhood:Moore symmetries: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 0 2 0 64 255 """ self.saverule(self.rulename, comments, table, colours) # Adapted from Golly's draw-lines.py by Andrew Trevorrow def 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 used bounds = '' 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.rulename rg.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, 0 if 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 Code: Select all  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 Code: Select all  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 Code: Select all  g.setrule("%s:P%d,%d" % (rg.rulename, wd, ht)) to Code: Select all  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 either all On cells or all Off cells without needing a bounded grid in Golly. Last edited by wildmyron on October 7th, 2019, 3:38 am, edited 1 time in total. The latest version of the 5S Project contains over 226,000 spaceships. There is also a GitHub mirror of the collection. Tabulated pages up to period 160 (out of date) are available on the LifeWiki. KittyTac Posts: 533 Joined: December 21st, 2017, 9:58 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? wildmyron Posts: 1397 Joined: August 9th, 2013, 12:45 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 226,000 spaceships. There is also a GitHub mirror of the collection. Tabulated pages up to period 160 (out of date) are available on the LifeWiki. KittyTac Posts: 533 Joined: December 21st, 2017, 9:58 am Re: Script request thread I guess someone else can make it. Gamedziner Posts: 796 Joined: May 30th, 2016, 8:47 pm Location: Milky Way Galaxy: Planet Earth 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. Code: Select all x = 81, y = 96, rule = LifeHistory 58.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!


dvgrn
Moderator
Posts: 6710
Joined: May 17th, 2009, 11:00 pm