Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions cellular_automata/elementary_cellular_automaton.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
Elementary Cellular Automaton - Rule 30
---------------------------------------

A one-dimensional cellular automaton introduced by Stephen Wolfram.
Each cell's next state depends on its current state and its two immediate neighbors.

Reference:
https://en.wikipedia.org/wiki/Rule_30
"""


def rule_30_step(current: list[int]) -> list[int]:
"""
Compute the next generation of a one-dimensional cellular automaton
following Wolfram's Rule 30.

Each cell's next state is determined by its left, center, and right neighbors.

Args:
current (list[int]): The current generation as a list of 0s (dead)
and 1s (alive).

Returns:
list[int]: The next generation as a list of 0s and 1s.

Example:
>>> rule_30_step([0, 0, 1, 0, 0])
[0, 1, 1, 1, 0]
"""
next_gen = []
for i in range(len(current)):
left = current[i - 1] if i > 0 else 0
center = current[i]
right = current[i + 1] if i < len(current) - 1 else 0

# Combine neighbors into a 3-bit pattern
pattern = (left << 2) | (center << 1) | right

# Rule 30 binary: 00011110 (bitwise representation of 30)
next_gen.append((30 >> pattern) & 1)

return next_gen


def generate_rule_30(size: int = 31, generations: int = 15) -> list[list[int]]:
"""
Generate multiple generations of Rule 30 automaton.

Args:
size (int): Number of cells in one generation. Default is 31.
generations (int): Number of generations to evolve. Default is 15.

Returns:
list[list[int]]: A list of generations (each a list of 0s and 1s).

Example:
>>> len(generate_rule_30(15, 5))
5
"""
grid = [[0] * size for _ in range(generations)]
grid[0][size // 2] = 1 # Start with a single live cell in the middle

for i in range(1, generations):
grid[i] = rule_30_step(grid[i - 1])

return grid


if __name__ == "__main__":
# Run an example simulation
generations = generate_rule_30(31, 15)
for row in generations:
print("".join("█" if cell else " " for cell in row))