Rule 30 is a one dimensional cellular automaton where only the cells in the previous generation are considered by the current generation. There are two states that a cell can be in: 1
or 0
. The rules for creating the next generation are represented in the row below, and depend on the cell immediately above the current cell, as well as it's immediate neighbours.
The cellular automaton is applied by the following rule (using bitwise operators):
left_cell ^ (central_cell | right_cell)
This rule forms the table below:
Now I tried to implement these rules into Python, using numpy. I defined an initial state that accepts width
as a parameter and produces an initial row of zeros with 1 in the middle.
def initial_state(width):
initial = np.zeros((1, width), dtype=int)
if width % 2 == 0:
initial = np.insert(initial, int(width / 2), values=0, axis=1)
initial[0, int(width / 2)] = 1
return initial
else:
initial[0, int(width / 2)] = 1
return initial
The function below just produces the second generation given an initial row. How do I create a for loop that keeps producing new generations until the first element of the last bottom row becomes 1?
def rule30(array):
row1 = np.pad(array,[(0,0), (1,1)], mode='constant')
next_row = array.copy()
for x in range(1, array.shape[0]+1):
for y in range(1, array.shape[1]+1):
if row1[x-1][y-1] == 1 ^ (row1[x-1][y] == 1 or row1[x-1][y+1] == 1):
next_row[x - 1, y - 1] = 1
else:
next_row[x - 1, y - 1] = 0
return np.concatenate((array, next_row))
For example, if the input is
A = [0, 0, 0, 1, 0, 0, 0]
The output should be
>>> print(rule30(A))
[[0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0],
[0, 1, 1, 0, 0, 1, 0],
[1, 1, 0, 1, 1, 1, 1]]