title: Generating rows of a rule 30 cellular automaton
body: <p>Rule 30 is a one dimensional cellular automaton where only the cells in the previous generation are considered by the current generation. There are two states that a cell can be in: <code>1</code> or <code>0</code>. The rules for creating the next generation are represented in the row below, and depend on the cell immediately above the current cell, as well as it's immediate neighbours.</p>
  
  <p>The cellular automaton is applied by the following rule (using bitwise operators):</p>
  
  <pre><code>left_cell ^ (central_cell | right_cell)
  </code></pre>
  
  <p>This rule forms the table below:</p>
  
  <p><a href="https://i.stack.imgur.com/UG2re.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/UG2re.png" alt="enter image description here"></a></p>
  
  <p>Now I tried to implement these rules into Python, using numpy. I defined an initial state that accepts <code>width</code> as a parameter and produces an initial row of zeros with 1 in the middle.</p>
  
  <pre><code>def initial_state(width):
      initial = np.zeros((1, width), dtype=int)
      if width % 2 == 0:
          initial = np.insert(initial, int(width / 2), values=0, axis=1)
          initial[0, int(width / 2)] = 1
          return initial
      else:
          initial[0, int(width / 2)] = 1
          return initial
  </code></pre>
  
  <p>The function below just produces the second generation given an initial row. How do I create a for loop that keeps producing new generations until the first element of the last bottom row becomes 1?</p>
  
  <pre><code>def rule30(array):
      row1 = np.pad(array,[(0,0), (1,1)], mode='constant')
      next_row = array.copy()
      for x in range(1, array.shape[0]+1):
          for y in range(1, array.shape[1]+1):
              if row1[x-1][y-1] == 1 ^ (row1[x-1][y] == 1 or row1[x-1][y+1] == 1):
                  next_row[x - 1, y - 1] = 1
              else:
                  next_row[x - 1, y - 1] = 0
          return np.concatenate((array, next_row))
  </code></pre>
  
  <p>For example, if the input is </p>
  
  <pre><code>A = [0, 0, 0, 1, 0, 0, 0]
  </code></pre>
  
  <p>The output should be</p>
  
  <pre><code>&gt;&gt;&gt; print(rule30(A))
  [[0, 0, 0, 1, 0, 0, 0],
   [0, 0, 1, 1, 1, 0, 0],
   [0, 1, 1, 0, 0, 1, 0],
   [1, 1, 0, 1, 1, 1, 1]]
  </code></pre>