Skip to content

Instantly share code, notes, and snippets.

@vyznev
Created February 3, 2018 08:40
Show Gist options
  • Save vyznev/9e168f6985a06cf9c7b1a510bf89999e to your computer and use it in GitHub Desktop.
Save vyznev/9e168f6985a06cf9c7b1a510bf89999e to your computer and use it in GitHub Desktop.
Convert pairs of isotropic CA rule strings on the 4-cell von Neumann neighborhood into a Logic Life Search partial rule dictionary.
#!/usr/bin/python
import re
import sys
import argparse
parser = argparse.ArgumentParser(description='Generate LLS rule dict to search multiple isotropic CA rules on the 4-cell von Neumann neighborhood.')
parser.add_argument('minrule', help='minimum rule string (e.g. B0/S)')
parser.add_argument('maxrule', nargs='?', help='maximum rule string (e.g. B0234/S01)')
parser.add_argument('-t', '--totalistic', action='store_true', help='consider only (outer) totalistic rules, i.e. treat 2e and 2i as equivalent')
args = parser.parse_args()
# map of von Neumann to Moore neighborhood codes (XXX: LLS uses "c" as dummy letter for 0 and 8 neighbors)
neumann2moore = {
"0": {0: "c", 1: "c", 2: "cn", 3: "c", 4: "c"},
"1": {1: "e", 2: "ka", 3: "inyq", 4: "ny", 5: "e"},
"2e": {2: "e", 3: "kaj", 4: "kaqw", 5: "kaj", 6: "e"},
"2i": {2: "i", 3: "r", 4: "itz", 5: "r", 6: "i"},
"3": {3: "e", 4: "jr", 5: "inyq", 6: "ka", 7: "e"},
"4": {4: "e", 5: "c", 6: "cn", 7: "c", 8: "c"}
}
# the allowed suffix letters for neighbor count n are moore_letters[:letter_counts[n]]
moore_letters = "cekainyqjrtwz"
letter_counts = [1,2,6,10,13,10,6,2,1]
# prefill rule table with zeros
rule = {}
for count in range(9):
for letter in moore_letters[:letter_counts[count]]:
for bs in "BS":
rule[bs + str(count) + letter] = "0"
# add rule bits to table
def convert_env(rule, envstr4, bs, force=True, totalistic=False):
for match in re.finditer(r'([0-4])(-?)([ei]*)', envstr4):
count = match.group(1)
if count == "2":
negate = bool(match.group(2))
letters = set(match.group(3))
if negate or not letters: letters = set("ei") - letters
else:
letters = [""]
for letter in letters:
sym = "1" if force else bs + count + ("" if totalistic else letter) + "V"
for count8, letters8 in neumann2moore[count + letter].items():
for letter8 in letters8:
rule[bs + str(count8) + letter8] = sym
def convert_rule(rule, rulestr, force=True, totalistic=False):
match = re.match(r'^\s*b((?:[0134]|2-?[ei]*)*)/s((?:[0134]|2-?[ei]*)*)[vn]?\s*$', rulestr.lower())
if not match:
sys.stderr.write("Cannot parse von Neumann rule \"%s\".\n" % rulestr)
sys.exit(1)
convert_env(rule, match.group(1), "B", force, totalistic)
convert_env(rule, match.group(2), "S", force, totalistic)
if args.maxrule is None:
args.maxrule = args.minrule
convert_rule(rule, args.maxrule, False, args.totalistic)
convert_rule(rule, args.minrule, True, args.totalistic)
print(repr(rule))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment