return an image of 16 generations of onedimensional cellular automata based on a given ruleset number https mathworld wolfram comelementarycellularautomaton html define the first generation of cells fmt off fmt on formatruleset11100 0 0 0 1 1 1 0 0 formatruleset0 0 0 0 0 0 0 0 0 formatruleset11111111 1 1 1 1 1 1 1 1 get the neighbors of each cell handle neighbours outside bounds by using 0 as their value define a new cell and add it to the new generation convert the cells into a greyscale pil image image and return it to the caller from random import random cells random for w in range31 for h in range16 img generateimagecells isinstanceimg image image true img width img height 31 16 create the output image generates image uncomment to save the image img savefrulerulenum png define the first generation of cells fmt off fmt on format_ruleset 11100 0 0 0 1 1 1 0 0 format_ruleset 0 0 0 0 0 0 0 0 0 format_ruleset 11111111 1 1 1 1 1 1 1 1 31 get the neighbors of each cell handle neighbours outside bounds by using 0 as their value define a new cell and add it to the new generation convert the cells into a greyscale pil image image and return it to the caller from random import random cells random for w in range 31 for h in range 16 img generate_image cells isinstance img image image true img width img height 31 16 create the output image generates image uncomment to save the image img save f rule_ rule_num png
from __future__ import annotations

from PIL import Image



CELLS = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]



def format_ruleset(ruleset: int) -> list[int]:
    
    return [int(c) for c in f"{ruleset:08}"[:8]]


def new_generation(cells: list[list[int]], rule: list[int], time: int) -> list[int]:
    population = len(cells[0])  
    next_generation = []
    for i in range(population):
        
        
        left_neighbor = 0 if i == 0 else cells[time][i - 1]
        right_neighbor = 0 if i == population - 1 else cells[time][i + 1]
        
        situation = 7 - int(f"{left_neighbor}{cells[time][i]}{right_neighbor}", 2)
        next_generation.append(rule[situation])
    return next_generation


def generate_image(cells: list[list[int]]) -> Image.Image:
    
    
    img = Image.new("RGB", (len(cells[0]), len(cells)))
    pixels = img.load()
    
    for w in range(img.width):
        for h in range(img.height):
            color = 255 - int(255 * cells[h][w])
            pixels[w, h] = (color, color, color)
    return img


if __name__ == "__main__":
    rule_num = bin(int(input("Rule:\n").strip()))[2:]
    rule = format_ruleset(int(rule_num))
    for time in range(16):
        CELLS.append(new_generation(CELLS, rule, time))
    img = generate_image(CELLS)
    
    
    img.show()