|
| 1 | +""" |
| 2 | +Elementary Cellular Automaton - Rule 30 |
| 3 | +--------------------------------------- |
| 4 | +
|
| 5 | +A one-dimensional cellular automaton introduced by Stephen Wolfram. |
| 6 | +Each cell's next state depends on its current state and its two immediate neighbors. |
| 7 | +
|
| 8 | +Reference: |
| 9 | +https://en.wikipedia.org/wiki/Rule_30 |
| 10 | +""" |
| 11 | + |
| 12 | +from typing import List |
| 13 | + |
| 14 | + |
| 15 | +def rule_30_step(current: List[int]) -> List[int]: |
| 16 | + """ |
| 17 | + Compute the next generation of a one-dimensional cellular automaton |
| 18 | + following Wolfram's Rule 30. |
| 19 | +
|
| 20 | + Each cell's next state is determined by its left, center, and right neighbors. |
| 21 | +
|
| 22 | + Args: |
| 23 | + current (List[int]): The current generation as a list of 0s (dead) and 1s (alive). |
| 24 | +
|
| 25 | + Returns: |
| 26 | + List[int]: The next generation as a list of 0s and 1s. |
| 27 | +
|
| 28 | + Example: |
| 29 | + >>> rule_30_step([0, 0, 1, 0, 0]) |
| 30 | + [0, 1, 1, 1, 0] |
| 31 | + """ |
| 32 | + next_gen = [] |
| 33 | + for i in range(len(current)): |
| 34 | + left = current[i - 1] if i > 0 else 0 |
| 35 | + center = current[i] |
| 36 | + right = current[i + 1] if i < len(current) - 1 else 0 |
| 37 | + |
| 38 | + # Combine neighbors into a 3-bit pattern |
| 39 | + pattern = (left << 2) | (center << 1) | right |
| 40 | + |
| 41 | + # Rule 30 binary: 00011110 -> 30 in decimal |
| 42 | + next_gen.append((30 >> pattern) & 1) |
| 43 | + |
| 44 | + return next_gen |
| 45 | + |
| 46 | + |
| 47 | +def generate_rule_30( |
| 48 | + size: int = 31, generations: int = 15 |
| 49 | +) -> List[List[int]]: |
| 50 | + """ |
| 51 | + Generate multiple generations of Rule 30 automaton. |
| 52 | +
|
| 53 | + Args: |
| 54 | + size (int): Number of cells in one generation. |
| 55 | + generations (int): Number of generations to evolve. |
| 56 | +
|
| 57 | + Returns: |
| 58 | + List[List[int]]: A list of generations (each a list of 0s and 1s). |
| 59 | +
|
| 60 | + Example: |
| 61 | + >>> len(generate_rule_30(15, 5)) |
| 62 | + 5 |
| 63 | + """ |
| 64 | + grid = [[0] * size for _ in range(generations)] |
| 65 | + grid[0][size // 2] = 1 # Start with a single live cell in the middle |
| 66 | + |
| 67 | + for i in range(1, generations): |
| 68 | + grid[i] = rule_30_step(grid[i - 1]) |
| 69 | + |
| 70 | + return grid |
| 71 | + |
| 72 | + |
| 73 | +if __name__ == "__main__": |
| 74 | + # Run an example simulation |
| 75 | + generations = generate_rule_30(31, 15) |
| 76 | + for row in generations: |
| 77 | + print("".join("█" if cell else " " for cell in row)) |
0 commit comments