-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyramid.py
More file actions
139 lines (117 loc) · 3.8 KB
/
pyramid.py
File metadata and controls
139 lines (117 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import os, sys, getopt
import timing
from PIL import Image
def main(argv):
""" Main Function """
## Defaults sim size ##
iterate = False
DEFAULT_WIDTH = 150
width = DEFAULT_WIDTH
steps = DEFAULT_WIDTH>>1
## Defaults rule ##
rule = 30
rules = [0x01&(rule>>(x)) for x in range(8)]
try:
opts, args = getopt.getopt(argv,"hir:w:s:sd:",["help","iterate","rule=","width=","steps=","start-distribution="])
except getopt.GetoptError:
print_help()
sys.exit(2)
for opt, arg in opts:
if opt in ('-h', '--help'):
print_help()
print("\nDefault args: [Iterate: {}, Rule: {}, Width: {}, Height: {}]".format(iterate, rule, width, steps))
sys.exit()
elif opt in ("-i", "--iterate"):
iterate = True
elif opt in ("-r", "--rule"):
if int(arg) not in range(256):
print("Rule must be an integer in [0,255]")
sys.exit()
else:
rules = [0x01&(int(arg)>>(x)) for x in range(8)]
elif opt in ("-w", "--width"):
width = int(arg)
steps = width>>1
elif opt in ("-s", "--steps"):
steps = int(arg)
elif opt in ("-sd", "--start-distribution"):
steps = int(arg)
## Defaults starting condition ##
data = [[0 for e in range(width)]]
data[0][width>>1] = 1
if iterate:
iterate_all_rules(width, steps)
else:
## Save and print specific rule ###
implement_rules(data,rules,steps)
save2image(data, rules)
print2image(data, rules)
def iterate_all_rules(width, steps):
""" Iterate through all rule combinations, saving to JPEG files """
for x in range(258):
data = [[0 for element in range(width)]]
data[0][width>>1] = 1
rules = [0x1&(x>>(7-y)) for y in range(8)]
implement_rules(data,rules,steps)
save2image(data, rules)
def print_help():
print("This script simulates elementary (1 dimensional) cellular automata.")
print("\t-r specifies a rule number. Interesting rules can be found at https://en.wikipedia.org/wiki/Elementary_cellular_automaton")
print("\t-w specifies a simulation width, and automatically sets steps to width / 2.")
print("\t-s overrides default step length")
print("\t-i sets to 'iterate mode'. This iterates and saves-to-image all 256 rules.")
print("\nSome examples:")
print("\tpyramid.py -i (iterate all rules) -w <width>")
print("\tpyramid.py -r <rule # (integer)> -w <width> -s <steps>")
def save2image(ptr, rules):
""" Saves 2D list to JPEG in current folder """
im = Image.new("1", (len(ptr[0]), len(ptr)))
sequence = [ptr[x][y] for x in range(len(ptr)) for y in range(len(ptr[0]))]
im.putdata(sequence)
rule = 0
for i,e in enumerate(rules):
rule += e<<i
path = "images/"
name = "pyramid_{}x{}_{}".format(len(ptr[0]),len(ptr), rule)
ext = ".jpeg"
try:
os.stat(path)
except:
os.mkdir(path)
im.save(path+name+ext)
def print2image(ptr, rules):
""" Prints 2D list as JPEG """
im = Image.new("1", (len(ptr[0]), len(ptr)))
sequence = [ptr[x][y] for x in range(len(ptr)) for y in range(len(ptr[0]))]
im.putdata(sequence)
im.show()
def map(row, indices):
""" Computes integer value of three 'overhead' blocks as binary """
num = 0
width = len(row)
for i,index in enumerate(indices):
if index[1] < 0 or index[1] >= width:
continue
else:
num += row[index[1]]<<(2-i)
return num
def implement_rules(data, rules, steps):
""" Carries out rules on data, appending new data """
""" data is a list of lists of desired width """
""" rules is list where the nth element """
""" corresponds to binary interpretation of the three overhead values. """
""" For example: """
""" 0 1 0 1 1 """
""" x """
""" x will be replaced by rules[hex2int('101')] """
width = len(data[0])
for row in range(steps):
newRow = []
for col in range(width):
indices = [[row,col+x] for x in range(-1,2)]
rule = map(data[row], indices)
newRow.append(rules[rule])
data.append(newRow)
return data
if __name__ == '__main__':
main(sys.argv[1:])