Last active
February 3, 2018 02:41
-
-
Save vyznev/92a53d9079b5cdff6308372ccc5aa37a to your computer and use it in GitHub Desktop.
Convert isotropic CA rule strings from the 4-cell von Neumann neighborhood to the 8-cell Moore neighborhood
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
neumann2moore = { | |
"0": {0: "", 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: ""} | |
} | |
# the allowed suffix letters for neighbor count n are moore_letters[:letter_counts[n]] | |
moore_letters = "cekainyqjrtwz" | |
letter_counts = [0,2,6,10,13,10,6,2,0] | |
def convert_env(envstr4): | |
env8 = {} | |
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: | |
for count8, letters8 in neumann2moore[count + letter].items(): | |
if count8 not in env8: env8[count8] = set() | |
env8[count8] |= set(letters8) | |
# generate canonical output string | |
envstr8 = "" | |
for count, letters in sorted(env8.items()): | |
complement = set(moore_letters[:letter_counts[count]]) - letters | |
if len(complement) == 0: | |
envstr8 += str(count) | |
elif len(complement) < len(letters): | |
envstr8 += str(count) + "-" + "".join(sorted(complement)) | |
else: | |
envstr8 += str(count) + "".join(sorted(letters)) | |
return envstr8 | |
import argparse | |
parser = argparse.ArgumentParser(description='Convert isotropic CA rule from 4-cell von Neumann to 8-cell Moore neighborhood.') | |
parser.add_argument('rule', nargs='+', help='input rule (e.g. B024/S1)') | |
args = parser.parse_args() | |
import re | |
import sys | |
ok = True | |
for rule in args.rule: | |
bs = re.match(r'^\s*b((?:[0134]|2-?[ei]*)*)/s((?:[0134]|2-?[ei]*)*)[vn]?\s*$', rule.lower()) | |
if bs: | |
bs = tuple(convert_env(bs.group(i)) for i in (1,2)) | |
print("B%s/S%s" % bs) | |
else: | |
sys.stderr.write("Cannot parse von Neumann rule \"%s\".\n" % rule) | |
ok = False | |
if not ok: sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment