# -*- coding: utf-8 -*-

"""
Report 5: Cellular Automata

A cellular automaton is a self-contained universe where its space is divided
into a grid of cells, and has its own "laws of physics". 

Each cell in the grid has its own state and a set of neighbors.

Time in this universe is a discrete set of steps. At each step of time, a
transition rule updates the state of every cell based on the current state of
the cell and its neighbors.
"""


import numpy as np
import matplotlib.pyplot as plt


def cell_auto():
    
    """
    Method to create a 2 x 2 subplot containing 4 plots with diffent cellular 
    automaton. Cellular automata have the following characteristics:
        - A one dimensional grid with each cell having just two neighbors, one
        on each side.
        - Four possible cell states: 1, 2, 3, 4, that are represented by a 
        different color.
        - Periodic edge conditions: the rightmost and leftmost cells are
        neighbors.
        - The transition rule is that the state of each cell is updated based
        on the sum of the current cell state and those of its neighbors.
    
    All cellular automata change everytime the function is run.
    
    Parameters:
        None
    
    Returns:
        None
    """
    
    
    nGen = 25 # number of generations to apply transition rule to
    nCells = 25 # number of cells
    
    colors = np.array([[1, 0, 0], [0, 1, 1], [0.5, 0, 1], [1, 1, 0]], 
                      dtype = float) # red, cyan, purple, yellow
    
    plt.figure(figsize = (10, 10))
    
    nRow = 2
    nCol = 2
    
    for j in range(1, nRow*nCol + 1):
        cellState = np.empty((nGen, nCells), dtype = int)
        cellState[0] = np.random.randint(4, size = nCells)
        rule = np.random.randint(4, size = 10) # transition rule
        
        for i in range(1, nGen):
            sumCells = (cellState[i-1] + np.roll(cellState[i-1], -1) 
                        + np.roll(cellState[i-1], 1))
            
            cellState[i] = rule[sumCells]
        
        
        cellColor = colors[cellState]
        
        plt.subplot(nRow, nCol, j)
        plt.subplots_adjust(wspace = 0.5)
        plt.imshow(cellColor, interpolation = 'None')
        
        plt.title(str(j), fontsize = 16)
        plt.xlabel(str(rule), fontsize = 16)
        plt.xticks([])
        plt.yticks([])