#! /usr/bin/env python3
"""Take an initial row and a cellular automaton rule and run the
automaton for a given number of iterations"""
import random
def main():
n_steps = 2000
n_cells = 550
row = set_first_row_random(n_cells)
# row = set_first_row_specific_points(n_cells, [270])
# row = set_first_row_specific_points(n_cells, [200, 380])
print_row(row)
# rule = '01101000' # the basic rule
# rule = '00011110' # the famous rule 30
rule = '01101110' # the famous rule 110
for i in range(n_steps):
row = take_step(rule, row)
print_row(row)
def take_step(rule, row):
"""a single iteration of the cellular automaton"""
n_cells = len(row)
new_row = [0]*n_cells
for i in range(n_cells):
neighbors = [row[(i - 1 + n_cells) % n_cells], row[i], row[(i + 1) % n_cells]]
# new_row[i] = new_cell(neighbors)
## NOTE: new_cell_with_rule() is part of the extended code (at
## the bottom)
new_row[i] = new_cell_with_rule(rule, neighbors)
return new_row
def new_cell(neighbors):
"""looks at the neighborhood of three cells and determine what the
successor of the central cell should be"""
## this simple approach decides on the next cell based on the sum
## of the neighbors -- if both neighbors are active we are
## overcrowded and we die; if one is active then we come to life;
## if none are active we starve and die.
if neighbors[0] + neighbors[2] == 2: # try [0] and [1] for a different pattern
new_cell = 0
elif neighbors[0] + neighbors[2] == 1:
new_cell = 1
else:
new_cell = 0
return new_cell
def set_first_row_random(n_cells):
"""sets the first row to random values"""
row = [0]*n_cells
for i in range(n_cells):
row[i] = random.randint(0, 1)
return row
def set_first_row_specific_points(n_cells, active_pts):
"""takes a list of specific cells to be activated in the first row"""
row = [0]*n_cells
for pt in active_pts: # only activate the given cells
print(pt)
row[pt] = 1
return row
def print_row(row):
"""prints a row, represented as a blank if the cell is 0 or a special
symbol (like a period) if it's 1"""
on_marker = 'x'
row_str = ''
for cell in row:
if cell:
symbol = on_marker
else:
symbol = ' '
print(symbol, end="")
print()
## NOTE: new_cell_with_rule() is extended code; you can skip it on a
## first implementation
def new_cell_with_rule(rule, neighbors):
"""Applies a rule encoded as a binary string -- since a neighborhood
of 3 binary cells can have 8 possible patterns, it's a string of 8
bits. You can modify it to be any of the 256 possible strings of
8 bits. I provide a couple of examples, and you can try many others."""
if not rule:
rule = '01101000' # the default rule
rule_index = neighbors[0] + 2*neighbors[1] + 4*neighbors[2]
cell = int(rule[rule_index])
return cell
if __name__ == '__main__':
main()