Elementary cellular automaton: Difference between revisions

From Rosetta Code
Content added Content deleted
(Undo revision 178749 by Dkf My question on the talk page to Elementary cellular automaton/Random Number Generator‎; may cause a change in this.)
(→‎{{header|Python}}: Extend with two other types of padding.)
Line 277: Line 277:


=={{header|Python}}==
=={{header|Python}}==
===Python: Zero padded===
<lang python>def eca(cells, rule):
<lang python>def eca(cells, rule):
lencells = len(cells)
lencells = len(cells)
Line 290: Line 291:
yield c[1:-1]
yield c[1:-1]


if __name__ == '__main__':
for rule in (90, 30, 122):
lines, start, rules = 50, '0000000001000000000', (90, 30, 122)
print('\nRule: %i' % rule)
for i, c in zip(range(16), eca('0000000001000000000', rule)):
zipped = [range(lines)] + [eca(start, rule) for rule in rules]
print('%2i: %s' % (i, c.replace('0', '.').replace('1', '#')))</lang>
print('\n Rules: %r' % (rules,))
for data in zip(*zipped):
i = data[0]
cells = data[1:]
print('%2i: %s' % (i, ' '.join(cells).replace('0', '.').replace('1', '#')))</lang>


{{out}}
{{out}}
<pre>Rule: 90
<pre> Rules: (90, 30, 122)
0: .........#.........
0: .........#......... .........#......... .........#.........
1: ........#.#........
1: ........#.#........ ........###........ ........#.#........
2: .......#...#.......
2: .......#...#....... .......##..#....... .......#.#.#.......
3: ......#.#.#.#......
3: ......#.#.#.#...... ......##.####...... ......#.#.#.#......
4: .....#.......#.....
4: .....#.......#..... .....##..#...#..... .....#.#.#.#.#.....
5: ....#.#.....#.#....
5: ....#.#.....#.#.... ....##.####.###.... ....#.#.#.#.#.#....
6: ...#...#...#...#...
6: ...#...#...#...#... ...##..#....#..#... ...#.#.#.#.#.#.#...
7: ..#.#.#.#.#.#.#.#..
7: ..#.#.#.#.#.#.#.#.. ..##.####..######.. ..#.#.#.#.#.#.#.#..
8: .#...............#.
8: .#...............#. .##..#...###.....#. .#.#.#.#.#.#.#.#.#.
9: #.#.............#.#
9: #.#.............#.# ##.####.##..#...### #.#.#.#.#.#.#.#.#.#
10: ...#...........#...
10: ...#...........#... #..#....#.####.##.. .#.#.#.#.#.#.#.#.#.
11: ..#.#.........#.#..
11: ..#.#.........#.#.. #####..##.#....#.#. #.#.#.#.#.#.#.#.#.#
12: .#...#.......#...#.
12: .#...#.......#...#. #....###..##..##.## .#.#.#.#.#.#.#.#.#.
13: #.#.#.#.....#.#.#.#
13: #.#.#.#.....#.#.#.# ##..##..###.###..#. #.#.#.#.#.#.#.#.#.#
14: .......#...#.......
14: .......#...#....... #.###.###...#..#### .#.#.#.#.#.#.#.#.#.
15: ......#.#.#.#......
15: ......#.#.#.#...... #.#...#..#.#####... #.#.#.#.#.#.#.#.#.#
16: .....#.......#..... #.##.#####.#....#.. .#.#.#.#.#.#.#.#.#.
17: ....#.#.....#.#.... #.#..#.....##..###. #.#.#.#.#.#.#.#.#.#
18: ...#...#...#...#... #.#####...##.###..# .#.#.#.#.#.#.#.#.#.
19: ..#.#.#.#.#.#.#.#.. #.#....#.##..#..### #.#.#.#.#.#.#.#.#.#
20: .#...............#. #.##..##.#.######.. .#.#.#.#.#.#.#.#.#.
21: #.#.............#.# #.#.###..#.#.....#. #.#.#.#.#.#.#.#.#.#
22: ...#...........#... #.#.#..###.##...### .#.#.#.#.#.#.#.#.#.
23: ..#.#.........#.#.. #.#.####...#.#.##.. #.#.#.#.#.#.#.#.#.#
24: .#...#.......#...#. #.#.#...#.##.#.#.#. .#.#.#.#.#.#.#.#.#.
25: #.#.#.#.....#.#.#.# #.#.##.##.#..#.#.## #.#.#.#.#.#.#.#.#.#
26: .......#...#....... #.#.#..#..####.#.#. .#.#.#.#.#.#.#.#.#.
27: ......#.#.#.#...... #.#.#######....#.## #.#.#.#.#.#.#.#.#.#
28: .....#.......#..... #.#.#......#..##.#. .#.#.#.#.#.#.#.#.#.
29: ....#.#.....#.#.... #.#.##....#####..## #.#.#.#.#.#.#.#.#.#
30: ...#...#...#...#... #.#.#.#..##....###. .#.#.#.#.#.#.#.#.#.
31: ..#.#.#.#.#.#.#.#.. #.#.#.####.#..##..# #.#.#.#.#.#.#.#.#.#
32: .#...............#. #.#.#.#....####.### .#.#.#.#.#.#.#.#.#.
33: #.#.............#.# #.#.#.##..##....#.. #.#.#.#.#.#.#.#.#.#
34: ...#...........#... #.#.#.#.###.#..###. .#.#.#.#.#.#.#.#.#.
35: ..#.#.........#.#.. #.#.#.#.#...####..# #.#.#.#.#.#.#.#.#.#
36: .#...#.......#...#. #.#.#.#.##.##...### .#.#.#.#.#.#.#.#.#.
37: #.#.#.#.....#.#.#.# #.#.#.#.#..#.#.##.. #.#.#.#.#.#.#.#.#.#
38: .......#...#....... #.#.#.#.####.#.#.#. .#.#.#.#.#.#.#.#.#.
39: ......#.#.#.#...... #.#.#.#.#....#.#.## #.#.#.#.#.#.#.#.#.#
40: .....#.......#..... #.#.#.#.##..##.#.#. .#.#.#.#.#.#.#.#.#.
41: ....#.#.....#.#.... #.#.#.#.#.###..#.## #.#.#.#.#.#.#.#.#.#
42: ...#...#...#...#... #.#.#.#.#.#..###.#. .#.#.#.#.#.#.#.#.#.
43: ..#.#.#.#.#.#.#.#.. #.#.#.#.#.####...## #.#.#.#.#.#.#.#.#.#
44: .#...............#. #.#.#.#.#.#...#.##. .#.#.#.#.#.#.#.#.#.
45: #.#.............#.# #.#.#.#.#.##.##.#.# #.#.#.#.#.#.#.#.#.#
46: ...#...........#... #.#.#.#.#.#..#..#.# .#.#.#.#.#.#.#.#.#.
47: ..#.#.........#.#.. #.#.#.#.#.#######.# #.#.#.#.#.#.#.#.#.#
48: .#...#.......#...#. #.#.#.#.#.#.......# .#.#.#.#.#.#.#.#.#.
49: #.#.#.#.....#.#.#.# #.#.#.#.#.##.....## #.#.#.#.#.#.#.#.#.#</pre>


===Python: wrap===
Rule: 30
The ends of the cells wrap-around.
0: .........#.........
<lang python>def eca_wrap(cells, rule):
1: ........###........
lencells = len(cells)
2: .......##..#.......
rulebits = '{0:08b}'.format(rule)
3: ......##.####......
neighbours2next = {tuple('{0:03b}'.format(n)):rulebits[::-1][n] for n in range(8)}
4: .....##..#...#.....
c = cells
5: ....##.####.###....
while True:
6: ...##..#....#..#...
yield c
7: ..##.####..######..
c = ''.join(neighbours2next[(c[i-1], c[i], c[(i+1) % lencells])] for i in range(lencells))
8: .##..#...###.....#.
9: ##.####.##..#...###
10: #..#....#.####.##..
11: #####..##.#....#.#.
12: #....###..##..##.##
13: ##..##..###.###..#.
14: #.###.###...#..####
15: #.#...#..#.#####...


if __name__ == '__main__':
Rule: 122
lines, start, rules = 50, '0000000001000000000', (90, 30, 122)
0: .........#.........
zipped = [range(lines)] + [eca_wrap(start, rule) for rule in rules]
1: ........#.#........
print('\n Rules: %r' % (rules,))
2: .......#.#.#.......
for data in zip(*zipped):
3: ......#.#.#.#......
i = data[0]
4: .....#.#.#.#.#.....
cells = data[1:]
5: ....#.#.#.#.#.#....
print('%2i: %s' % (i, ' '.join(cells).replace('0', '.').replace('1', '#')))
6: ...#.#.#.#.#.#.#...
</lang>
7: ..#.#.#.#.#.#.#.#..

8: .#.#.#.#.#.#.#.#.#.
{{out}}
9: #.#.#.#.#.#.#.#.#.#
<pre> Rules: (90, 30, 122)
10: .#.#.#.#.#.#.#.#.#.
0: .........#......... .........#......... .........#.........
11: #.#.#.#.#.#.#.#.#.#
12: .#.#.#.#.#.#.#.#.#.
1: ........#.#........ ........###........ ........#.#........
13: #.#.#.#.#.#.#.#.#.#
2: .......#...#....... .......##..#....... .......#.#.#.......
14: .#.#.#.#.#.#.#.#.#.
3: ......#.#.#.#...... ......##.####...... ......#.#.#.#......
15: #.#.#.#.#.#.#.#.#.#</pre>
4: .....#.......#..... .....##..#...#..... .....#.#.#.#.#.....
5: ....#.#.....#.#.... ....##.####.###.... ....#.#.#.#.#.#....
6: ...#...#...#...#... ...##..#....#..#... ...#.#.#.#.#.#.#...
7: ..#.#.#.#.#.#.#.#.. ..##.####..######.. ..#.#.#.#.#.#.#.#..
8: .#...............#. .##..#...###.....#. .#.#.#.#.#.#.#.#.#.
9: #.#.............#.# ##.####.##..#...### #.#.#.#.#.#.#.#.#.#
10: #..#...........#..# ...#....#.####.##.. ##.#.#.#.#.#.#.#.##
11: ###.#.........#.### ..###..##.#....#.#. .##.#.#.#.#.#.#.##.
12: ..#..#.......#..#.. .##..###..##..##.## ####.#.#.#.#.#.####
13: .#.##.#.....#.##.#. .#.###..###.###..#. ...##.#.#.#.#.##...
14: #..##..#...#..##..# ##.#..###...#..#### ..####.#.#.#.####..
15: #######.#.#.####### ...####..#.#####... .##..##.#.#.##..##.
16: ......#.....#...... ..##...###.#....#.. ########.#.########
17: .....#.#...#.#..... .##.#.##...##..###. .......##.##.......
18: ....#...#.#...#.... ##..#.#.#.##.###..# ......#######......
19: ...#.#.#...#.#.#... ..###.#.#.#..#..### .....##.....##.....
20: ..#.....#.#.....#.. ###...#.#.#######.. ....####...####....
21: .#.#...#...#...#.#. #..#.##.#.#......## ...##..##.##..##...
22: #...#.#.#.#.#.#...# .###.#..#.##....##. ..###############..
23: ##.#...........#.## ##...####.#.#..##.# .##.............##.
24: .#..#.........#..#. ..#.##....#.####..# ####...........####
25: #.##.#.......#.##.# ###.#.#..##.#...### ...##.........##...
26: #.##..#.....#..##.# ....#.####..##.##.. ..####.......####..
27: #.####.#...#.####.# ...##.#...###..#.#. .##..##.....##..##.
28: #.#..#..#.#..#..#.# ..##..##.##..###.## ########...########
29: #..##.##...##.##..# ###.###..#.###...#. .......##.##.......
30: #####.###.###.##### #...#..###.#..#.##. ......#######......
31: ....#.#.#.#.#.#.... ##.#####...####.#.. .....##.....##.....
32: ...#...........#... #..#....#.##....### ....####...####....
33: ..#.#.........#.#.. .####..##.#.#..##.. ...##..##.##..##...
34: .#...#.......#...#. ##...###..#.####.#. ..###############..
35: #.#.#.#.....#.#.#.# #.#.##..###.#....#. .##.............##.
36: #......#...#......# #.#.#.###...##..##. ####...........####
37: ##....#.#.#.#....## #.#.#.#..#.##.###.. ...##.........##...
38: .##..#.......#..##. #.#.#.####.#..#..## ..####.......####..
39: #####.#.....#.##### ..#.#.#....#######. .##..##.....##..##.
40: ....#..#...#..#.... .##.#.##..##......# ########...########
41: ...#.##.#.#.##.#... .#..#.#.###.#....## .......##.##.......
42: ..#..##.....##..#.. .####.#.#...##..##. ......#######......
43: .#.#####...#####.#. ##....#.##.##.###.# .....##.....##.....
44: #..#...##.##...#..# ..#..##.#..#..#...# ....####...####....
45: ###.#.###.###.#.### ######..########.## ...##..##.##..##...
46: ..#...#.#.#.#...#.. ......###........#. ..###############..
47: .#.#.#.......#.#.#. .....##..#......### .##.............##.
48: #.....#.....#.....# #...##.####....##.. ####...........####
49: ##...#.#...#.#...## ##.##..#...#..##.## ...##.........##...</pre>

===Python: Infinite===
Pad and extend with inverse of end cells on each iteration.
<lang python>def _notcell(c):
return '0' if c == '1' else '1'

def eca_infinite(cells, rule):
lencells = len(cells)
rulebits = '{0:08b}'.format(rule)
neighbours2next = {'{0:03b}'.format(n):rulebits[::-1][n] for n in range(8)}
c = cells
while True:
yield c
c = _notcell(c[0])*2 + c + _notcell(c[-1])*2 # Extend and pad the ends

c = ''.join(neighbours2next[c[i-1:i+2]] for i in range(1,len(c) - 1))
#yield c[1:-1]

if __name__ == '__main__':
lines, start, rules = 20, '1', (90, 30, 122)
zipped = [range(lines)] + [eca_infinite(start, rule) for rule in rules]
print('\n Rules: %r' % (rules,))
for data in zip(*zipped):
i = data[0]
cells = ['%s%s%s' % (' '*(lines - i), c, ' '*(lines - i)) for c in data[1:]]
print('%2i: %s' % (i, ' '.join(cells).replace('0', '.').replace('1', '#')))</lang>

{{out}}
<pre> Rules: (90, 30, 122)
0: # # #
1: #.# ### #.#
2: #...# ##..# #.#.#
3: #.#.#.# ##.#### #.#.#.#
4: #.......# ##..#...# #.#.#.#.#
5: #.#.....#.# ##.####.### #.#.#.#.#.#
6: #...#...#...# ##..#....#..# #.#.#.#.#.#.#
7: #.#.#.#.#.#.#.# ##.####..###### #.#.#.#.#.#.#.#
8: #...............# ##..#...###.....# #.#.#.#.#.#.#.#.#
9: #.#.............#.# ##.####.##..#...### #.#.#.#.#.#.#.#.#.#
10: #...#...........#...# ##..#....#.####.##..# #.#.#.#.#.#.#.#.#.#.#
11: #.#.#.#.........#.#.#.# ##.####..##.#....#.#### #.#.#.#.#.#.#.#.#.#.#.#
12: #.......#.......#.......# ##..#...###..##..##.#...# #.#.#.#.#.#.#.#.#.#.#.#.#
13: #.#.....#.#.....#.#.....#.# ##.####.##..###.###..##.### #.#.#.#.#.#.#.#.#.#.#.#.#.#
14: #...#...#...#...#...#...#...# ##..#....#.###...#..###..#..# #.#.#.#.#.#.#.#.#.#.#.#.#.#.#
15: #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.# ##.####..##.#..#.#####..####### #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
16: #...............................# ##..#...###..####.#....###......# #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
17: #.#.............................#.# ##.####.##..###....##..##..#....### #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
18: #...#...........................#...# ##..#....#.###..#..##.###.####..##..# #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
19: #.#.#.#.........................#.#.#.# ##.####..##.#..######..#...#...###.#### #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
20: #.......#.......................#.......# ##..#...###..####.....####.###.##...#...# #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
21: #.#.....#.#.....................#.#.....#.# ##.####.##..###...#...##....#...#.#.###.### #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
22: #...#...#...#...................#...#...#...# ##..#....#.###..#.###.##.#..###.##.#.#...#..# #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
23: #.#.#.#.#.#.#.#.................#.#.#.#.#.#.#.# ##.####..##.#..###.#...#..####...#..#.##.###### #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#
24: #...............#...............#...............# ##..#...###..####...##.#####...#.#####.#..#.....# #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.# </pre>


=={{header|Tcl}}==
=={{header|Tcl}}==

Revision as of 01:07, 22 March 2014

Elementary cellular automaton is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

An elementary cellular automaton is a one-dimensional cellular automaton where there are two possible states (labeled 0 and 1) and the rule to determine the state of a cell in the next generation depends only on the current state of the cell and its two immediate neighbors. Those three values can be encoded with three bits.

The rules of evolution are then encoded with eight bits indicating the outcome of each of the eight possibilities 111, 110, 101, 100, 011, 010, 001 and 000 in this order. Thus for instance the rule 13 means that a state is updated to 1 only in the cases 011, 010 and 000, since 13 in binary is 0b00001101.

The purpose of this task is to create a subroutine, program or function that allows to create and visualize the evolution of any of the 256 possible elementary cellular automata of arbitrary space length and for any given initial state. You can demonstrate your solution with any automaton of your choice.

You can either produce an ASCII rendering of the state evolution or a PBM image.

You can deal with the limit conditions (what happens on the borders of the space) in any way you please.

This task is basically a generalization of one-dimensional cellular automaton.

C

64 cells, edges are cyclic. <lang c>#include <stdio.h>

  1. include <limits.h>

typedef unsigned long long ull;

  1. define N (sizeof(ull) * CHAR_BIT)
  2. define B(x) (1ULL << (x))

void evolve(ull state, int rule) { int i; ull st;

printf("Rule %d:\n", rule); do { st = state; for (i = N; i--; ) putchar(st & B(i) ? '#' : '.'); putchar('\n');

for (state = i = 0; i < N; i++) if (rule & B(7 & (st>>(i-1) | st<<(N+1-i)))) state |= B(i); } while (st != state); }

int main(int argc, char **argv) { evolve(B(N/2), 90); evolve(B(N/4)|B(N - N/4), 30); // well, enjoy the fireworks

return 0; }</lang>

Output:
Rule 90:
................................#...............................
...............................#.#..............................
..............................#...#.............................
.............................#.#.#.#............................
............................#.......#...........................
...........................#.#.....#.#..........................
..........................#...#...#...#.........................
.........................#.#.#.#.#.#.#.#........................
........................#...............#.......................
                     ---(output snipped)---

Go

<lang go>package main

import (

   "fmt"
   "math/big"
   "math/rand"
   "strings"

)

func main() {

   const cells = 20
   const generations = 9
   fmt.Println("Single 1, rule 90:")
   a := big.NewInt(1)
   a.Lsh(a, cells/2)
   elem(90, cells, generations, a)
   fmt.Println("Random intial state, rule 30:")
   a = big.NewInt(1)
   a.Rand(rand.New(rand.NewSource(3)), a.Lsh(a, cells))
   elem(30, cells, generations, a)

}

func elem(rule uint, cells, generations int, a *big.Int) {

   output := func() {
       fmt.Println(strings.Replace(strings.Replace(
           fmt.Sprintf("%0*b", cells, a), "0", " ", -1), "1", "#", -1))
   }
   output()
   a1 := new(big.Int)
   set := func(cell int, k uint) {
       a1.SetBit(a1, cell, rule>>k&1)
   }
   last := cells - 1
   for r := 0; r < generations; r++ {
       k := a.Bit(last) | a.Bit(0)<<1 | a.Bit(1)<<2
       set(0, k)
       for c := 1; c < last; c++ {
           k = k>>1 | a.Bit(c+1)<<2
           set(c, k)
       }
       set(last, k>>1|a.Bit(0)<<2)
       a, a1 = a1, a
       output()
   }

}</lang>

Output:
Single 1, rule 90:
         #          
        # #         
       #   #        
      # # # #       
     #       #      
    # #     # #     
   #   #   #   #    
  # # # # # # # #   
 #               #  
# #             # # 
Random intial state, rule 30:
 #   # #  ####     #
 ## ## ####   #   ##
 #  #  #   # ### ## 
######### ## #   # #
          #  ## ## #
#        #####  #  #
 #      ##    ######
 ##    ## #  ##     
## #  ##  #### #    
#  #### ###    ##  #

Perl

Translation of: Perl 6

<lang perl>use strict; use warnings;

package Automaton {

   sub new {

my $class = shift; my $rule = [ reverse split //, sprintf "%08b", shift ]; return bless { rule => $rule, cells => [ @_ ] }, $class;

   }
   sub next {

my $this = shift; my @previous = @{$this->{cells}}; $this->{cells} = [ @{$this->{rule}}[ map { 4*$previous[($_ - 1) % @previous] + 2*$previous[$_] + $previous[($_ + 1) % @previous] } 0 .. @previous - 1 ] ]; return $this;

   }
   use overload
   q{""} => sub {

my $this = shift; join , map { $_ ? '#' : ' ' } @{$this->{cells}}

   };

}

my @a = map 0, 1 .. 91; $a[45] = 1; my $a = Automaton->new(90, @a);

for (1..40) {

   print "|$a|\n"; $a->next;

}</lang>

Output:
|                                             #                                             |
|                                            # #                                            |
|                                           #   #                                           |
|                                          # # # #                                          |
|                                         #       #                                         |
|                                        # #     # #                                        |
|                                       #   #   #   #                                       |
|                                      # # # # # # # #                                      |
|                                     #               #                                     |
|                                    # #             # #                                    |
|                                   #   #           #   #                                   |
|                                  # # # #         # # # #                                  |
|                                 #       #       #       #                                 |
|                                # #     # #     # #     # #                                |
|                               #   #   #   #   #   #   #   #                               |
|                              # # # # # # # # # # # # # # # #                              |
|                             #                               #                             |
|                            # #                             # #                            |
|                           #   #                           #   #                           |
|                          # # # #                         # # # #                          |
|                         #       #                       #       #                         |
|                        # #     # #                     # #     # #                        |
|                       #   #   #   #                   #   #   #   #                       |
|                      # # # # # # # #                 # # # # # # # #                      |
|                     #               #               #               #                     |
|                    # #             # #             # #             # #                    |
|                   #   #           #   #           #   #           #   #                   |
|                  # # # #         # # # #         # # # #         # # # #                  |
|                 #       #       #       #       #       #       #       #                 |
|                # #     # #     # #     # #     # #     # #     # #     # #                |
|               #   #   #   #   #   #   #   #   #   #   #   #   #   #   #   #               |
|              # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #              |
|             #                                                               #             |
|            # #                                                             # #            |
|           #   #                                                           #   #           |
|          # # # #                                                         # # # #          |
|         #       #                                                       #       #         |
|        # #     # #                                                     # #     # #        |
|       #   #   #   #                                                   #   #   #   #       |
|      # # # # # # # #                                                 # # # # # # # #      |

Perl 6

<lang perl6>class Automaton {

   has ($.rule, @.cells);
   method gist { <| |>.join: @!cells.map({$_ ?? '#' !! ' '}).join }
   method code { $!rule.fmt("%08b").flip.comb }
   method succ {
       self.new: :$!rule, :cells(
           self.code[
                  (4 X* @!cells.rotate(-1))
               Z+ (2 X* @!cells)
               Z+       @!cells.rotate(1)
           ]
       )
   }

}

my $size = 10; my Automaton $a .= new:

   :rule(30),
   :cells( 0 xx $size, 1, 0 xx $size );

say $a++ for ^$size;</lang>

Output:
|          #          |
|         ###         |
|        ##  #        |
|       ## ####       |
|      ##  #   #      |
|     ## #### ###     |
|    ##  #    #  #    |
|   ## ####  ######   |
|  ##  #   ###     #  |
| ## #### ##  #   ### |

Unfortunately that version is somewhat slow due to the (as yet) unoptimized vector operations, as well as rebuilding the code every iteration. The following version runs about ten times faster and produces the same output: <lang perl6>class Automaton {

   has $.rule;
   has @.cells;
   has @.code;
   method new (|args) { self.bless(|args).init }
   method init { @!code ||= $!rule.fmt("%08b").flip.comb».Int; self; }
   method gist { <| |>.join: @!cells.map({$_ ?? '#' !! ' '}).join }
   method succ {
       my \size = +@!cells;
       self.new: :$!rule, :@!code, :cells(
           @!code[
               for ^size -> \i {
                   4 * @!cells[(i - 1) % size] +
                   2 * @!cells[i] +
                       @!cells[(i+1) % size];
               }
           ]
       );
   }

}

my $size = 10; my Automaton $a .= new:

   :rule(30),
   :cells( 0 xx $size, 1, 0 xx $size );

say $a++ for ^$size;</lang>

Python

Python: Zero padded

<lang python>def eca(cells, rule):

   lencells = len(cells)
   c = "0" + cells + "0"    # Zero pad the ends
   rulebits = '{0:08b}'.format(rule)
   neighbours2next = {'{0:03b}'.format(n):rulebits[::-1][n] for n in range(8)}
   yield c[1:-1]
   while True:
       c = .join(['0',
                    .join(neighbours2next[c[i-1:i+2]]
                            for i in range(1,lencells+1)),
                    '0'])
       yield c[1:-1]

if __name__ == '__main__':

   lines, start, rules = 50, '0000000001000000000', (90, 30, 122)
   zipped = [range(lines)] + [eca(start, rule) for rule in rules]
   print('\n   Rules: %r' % (rules,))
   for data in zip(*zipped):
       i = data[0]
       cells = data[1:]
       print('%2i: %s' % (i, '    '.join(cells).replace('0', '.').replace('1', '#')))</lang>
Output:
   Rules: (90, 30, 122)
 0: .........#.........    .........#.........    .........#.........
 1: ........#.#........    ........###........    ........#.#........
 2: .......#...#.......    .......##..#.......    .......#.#.#.......
 3: ......#.#.#.#......    ......##.####......    ......#.#.#.#......
 4: .....#.......#.....    .....##..#...#.....    .....#.#.#.#.#.....
 5: ....#.#.....#.#....    ....##.####.###....    ....#.#.#.#.#.#....
 6: ...#...#...#...#...    ...##..#....#..#...    ...#.#.#.#.#.#.#...
 7: ..#.#.#.#.#.#.#.#..    ..##.####..######..    ..#.#.#.#.#.#.#.#..
 8: .#...............#.    .##..#...###.....#.    .#.#.#.#.#.#.#.#.#.
 9: #.#.............#.#    ##.####.##..#...###    #.#.#.#.#.#.#.#.#.#
10: ...#...........#...    #..#....#.####.##..    .#.#.#.#.#.#.#.#.#.
11: ..#.#.........#.#..    #####..##.#....#.#.    #.#.#.#.#.#.#.#.#.#
12: .#...#.......#...#.    #....###..##..##.##    .#.#.#.#.#.#.#.#.#.
13: #.#.#.#.....#.#.#.#    ##..##..###.###..#.    #.#.#.#.#.#.#.#.#.#
14: .......#...#.......    #.###.###...#..####    .#.#.#.#.#.#.#.#.#.
15: ......#.#.#.#......    #.#...#..#.#####...    #.#.#.#.#.#.#.#.#.#
16: .....#.......#.....    #.##.#####.#....#..    .#.#.#.#.#.#.#.#.#.
17: ....#.#.....#.#....    #.#..#.....##..###.    #.#.#.#.#.#.#.#.#.#
18: ...#...#...#...#...    #.#####...##.###..#    .#.#.#.#.#.#.#.#.#.
19: ..#.#.#.#.#.#.#.#..    #.#....#.##..#..###    #.#.#.#.#.#.#.#.#.#
20: .#...............#.    #.##..##.#.######..    .#.#.#.#.#.#.#.#.#.
21: #.#.............#.#    #.#.###..#.#.....#.    #.#.#.#.#.#.#.#.#.#
22: ...#...........#...    #.#.#..###.##...###    .#.#.#.#.#.#.#.#.#.
23: ..#.#.........#.#..    #.#.####...#.#.##..    #.#.#.#.#.#.#.#.#.#
24: .#...#.......#...#.    #.#.#...#.##.#.#.#.    .#.#.#.#.#.#.#.#.#.
25: #.#.#.#.....#.#.#.#    #.#.##.##.#..#.#.##    #.#.#.#.#.#.#.#.#.#
26: .......#...#.......    #.#.#..#..####.#.#.    .#.#.#.#.#.#.#.#.#.
27: ......#.#.#.#......    #.#.#######....#.##    #.#.#.#.#.#.#.#.#.#
28: .....#.......#.....    #.#.#......#..##.#.    .#.#.#.#.#.#.#.#.#.
29: ....#.#.....#.#....    #.#.##....#####..##    #.#.#.#.#.#.#.#.#.#
30: ...#...#...#...#...    #.#.#.#..##....###.    .#.#.#.#.#.#.#.#.#.
31: ..#.#.#.#.#.#.#.#..    #.#.#.####.#..##..#    #.#.#.#.#.#.#.#.#.#
32: .#...............#.    #.#.#.#....####.###    .#.#.#.#.#.#.#.#.#.
33: #.#.............#.#    #.#.#.##..##....#..    #.#.#.#.#.#.#.#.#.#
34: ...#...........#...    #.#.#.#.###.#..###.    .#.#.#.#.#.#.#.#.#.
35: ..#.#.........#.#..    #.#.#.#.#...####..#    #.#.#.#.#.#.#.#.#.#
36: .#...#.......#...#.    #.#.#.#.##.##...###    .#.#.#.#.#.#.#.#.#.
37: #.#.#.#.....#.#.#.#    #.#.#.#.#..#.#.##..    #.#.#.#.#.#.#.#.#.#
38: .......#...#.......    #.#.#.#.####.#.#.#.    .#.#.#.#.#.#.#.#.#.
39: ......#.#.#.#......    #.#.#.#.#....#.#.##    #.#.#.#.#.#.#.#.#.#
40: .....#.......#.....    #.#.#.#.##..##.#.#.    .#.#.#.#.#.#.#.#.#.
41: ....#.#.....#.#....    #.#.#.#.#.###..#.##    #.#.#.#.#.#.#.#.#.#
42: ...#...#...#...#...    #.#.#.#.#.#..###.#.    .#.#.#.#.#.#.#.#.#.
43: ..#.#.#.#.#.#.#.#..    #.#.#.#.#.####...##    #.#.#.#.#.#.#.#.#.#
44: .#...............#.    #.#.#.#.#.#...#.##.    .#.#.#.#.#.#.#.#.#.
45: #.#.............#.#    #.#.#.#.#.##.##.#.#    #.#.#.#.#.#.#.#.#.#
46: ...#...........#...    #.#.#.#.#.#..#..#.#    .#.#.#.#.#.#.#.#.#.
47: ..#.#.........#.#..    #.#.#.#.#.#######.#    #.#.#.#.#.#.#.#.#.#
48: .#...#.......#...#.    #.#.#.#.#.#.......#    .#.#.#.#.#.#.#.#.#.
49: #.#.#.#.....#.#.#.#    #.#.#.#.#.##.....##    #.#.#.#.#.#.#.#.#.#

Python: wrap

The ends of the cells wrap-around. <lang python>def eca_wrap(cells, rule):

   lencells = len(cells)
   rulebits = '{0:08b}'.format(rule)
   neighbours2next = {tuple('{0:03b}'.format(n)):rulebits[::-1][n] for n in range(8)}
   c = cells
   while True:
       yield c
       c = .join(neighbours2next[(c[i-1], c[i], c[(i+1) % lencells])] for i in range(lencells))

if __name__ == '__main__':

   lines, start, rules = 50, '0000000001000000000', (90, 30, 122)
   zipped = [range(lines)] + [eca_wrap(start, rule) for rule in rules]
   print('\n   Rules: %r' % (rules,))
   for data in zip(*zipped):
       i = data[0]
       cells = data[1:]
       print('%2i: %s' % (i, '    '.join(cells).replace('0', '.').replace('1', '#')))

</lang>

Output:
   Rules: (90, 30, 122)
 0: .........#.........    .........#.........    .........#.........
 1: ........#.#........    ........###........    ........#.#........
 2: .......#...#.......    .......##..#.......    .......#.#.#.......
 3: ......#.#.#.#......    ......##.####......    ......#.#.#.#......
 4: .....#.......#.....    .....##..#...#.....    .....#.#.#.#.#.....
 5: ....#.#.....#.#....    ....##.####.###....    ....#.#.#.#.#.#....
 6: ...#...#...#...#...    ...##..#....#..#...    ...#.#.#.#.#.#.#...
 7: ..#.#.#.#.#.#.#.#..    ..##.####..######..    ..#.#.#.#.#.#.#.#..
 8: .#...............#.    .##..#...###.....#.    .#.#.#.#.#.#.#.#.#.
 9: #.#.............#.#    ##.####.##..#...###    #.#.#.#.#.#.#.#.#.#
10: #..#...........#..#    ...#....#.####.##..    ##.#.#.#.#.#.#.#.##
11: ###.#.........#.###    ..###..##.#....#.#.    .##.#.#.#.#.#.#.##.
12: ..#..#.......#..#..    .##..###..##..##.##    ####.#.#.#.#.#.####
13: .#.##.#.....#.##.#.    .#.###..###.###..#.    ...##.#.#.#.#.##...
14: #..##..#...#..##..#    ##.#..###...#..####    ..####.#.#.#.####..
15: #######.#.#.#######    ...####..#.#####...    .##..##.#.#.##..##.
16: ......#.....#......    ..##...###.#....#..    ########.#.########
17: .....#.#...#.#.....    .##.#.##...##..###.    .......##.##.......
18: ....#...#.#...#....    ##..#.#.#.##.###..#    ......#######......
19: ...#.#.#...#.#.#...    ..###.#.#.#..#..###    .....##.....##.....
20: ..#.....#.#.....#..    ###...#.#.#######..    ....####...####....
21: .#.#...#...#...#.#.    #..#.##.#.#......##    ...##..##.##..##...
22: #...#.#.#.#.#.#...#    .###.#..#.##....##.    ..###############..
23: ##.#...........#.##    ##...####.#.#..##.#    .##.............##.
24: .#..#.........#..#.    ..#.##....#.####..#    ####...........####
25: #.##.#.......#.##.#    ###.#.#..##.#...###    ...##.........##...
26: #.##..#.....#..##.#    ....#.####..##.##..    ..####.......####..
27: #.####.#...#.####.#    ...##.#...###..#.#.    .##..##.....##..##.
28: #.#..#..#.#..#..#.#    ..##..##.##..###.##    ########...########
29: #..##.##...##.##..#    ###.###..#.###...#.    .......##.##.......
30: #####.###.###.#####    #...#..###.#..#.##.    ......#######......
31: ....#.#.#.#.#.#....    ##.#####...####.#..    .....##.....##.....
32: ...#...........#...    #..#....#.##....###    ....####...####....
33: ..#.#.........#.#..    .####..##.#.#..##..    ...##..##.##..##...
34: .#...#.......#...#.    ##...###..#.####.#.    ..###############..
35: #.#.#.#.....#.#.#.#    #.#.##..###.#....#.    .##.............##.
36: #......#...#......#    #.#.#.###...##..##.    ####...........####
37: ##....#.#.#.#....##    #.#.#.#..#.##.###..    ...##.........##...
38: .##..#.......#..##.    #.#.#.####.#..#..##    ..####.......####..
39: #####.#.....#.#####    ..#.#.#....#######.    .##..##.....##..##.
40: ....#..#...#..#....    .##.#.##..##......#    ########...########
41: ...#.##.#.#.##.#...    .#..#.#.###.#....##    .......##.##.......
42: ..#..##.....##..#..    .####.#.#...##..##.    ......#######......
43: .#.#####...#####.#.    ##....#.##.##.###.#    .....##.....##.....
44: #..#...##.##...#..#    ..#..##.#..#..#...#    ....####...####....
45: ###.#.###.###.#.###    ######..########.##    ...##..##.##..##...
46: ..#...#.#.#.#...#..    ......###........#.    ..###############..
47: .#.#.#.......#.#.#.    .....##..#......###    .##.............##.
48: #.....#.....#.....#    #...##.####....##..    ####...........####
49: ##...#.#...#.#...##    ##.##..#...#..##.##    ...##.........##...

Python: Infinite

Pad and extend with inverse of end cells on each iteration. <lang python>def _notcell(c):

   return '0' if c == '1' else '1'

def eca_infinite(cells, rule):

   lencells = len(cells)
   rulebits = '{0:08b}'.format(rule)
   neighbours2next = {'{0:03b}'.format(n):rulebits[::-1][n] for n in range(8)}
   c = cells
   while True:
       yield c
       c = _notcell(c[0])*2 + c + _notcell(c[-1])*2    # Extend and pad the ends
       c = .join(neighbours2next[c[i-1:i+2]] for i in range(1,len(c) - 1))
       #yield c[1:-1]

if __name__ == '__main__':

   lines, start, rules = 20, '1', (90, 30, 122)
   zipped = [range(lines)] + [eca_infinite(start, rule) for rule in rules]
   print('\n   Rules: %r' % (rules,))
   for data in zip(*zipped):
       i = data[0]
       cells = ['%s%s%s' % (' '*(lines - i), c, ' '*(lines - i)) for c in data[1:]]
       print('%2i: %s' % (i, '    '.join(cells).replace('0', '.').replace('1', '#')))</lang>
Output:
   Rules: (90, 30, 122)
 0:                          #                                                      #                                                      #                         
 1:                         #.#                                                    ###                                                    #.#                        
 2:                        #...#                                                  ##..#                                                  #.#.#                       
 3:                       #.#.#.#                                                ##.####                                                #.#.#.#                      
 4:                      #.......#                                              ##..#...#                                              #.#.#.#.#                     
 5:                     #.#.....#.#                                            ##.####.###                                            #.#.#.#.#.#                    
 6:                    #...#...#...#                                          ##..#....#..#                                          #.#.#.#.#.#.#                   
 7:                   #.#.#.#.#.#.#.#                                        ##.####..######                                        #.#.#.#.#.#.#.#                  
 8:                  #...............#                                      ##..#...###.....#                                      #.#.#.#.#.#.#.#.#                 
 9:                 #.#.............#.#                                    ##.####.##..#...###                                    #.#.#.#.#.#.#.#.#.#                
10:                #...#...........#...#                                  ##..#....#.####.##..#                                  #.#.#.#.#.#.#.#.#.#.#               
11:               #.#.#.#.........#.#.#.#                                ##.####..##.#....#.####                                #.#.#.#.#.#.#.#.#.#.#.#              
12:              #.......#.......#.......#                              ##..#...###..##..##.#...#                              #.#.#.#.#.#.#.#.#.#.#.#.#             
13:             #.#.....#.#.....#.#.....#.#                            ##.####.##..###.###..##.###                            #.#.#.#.#.#.#.#.#.#.#.#.#.#            
14:            #...#...#...#...#...#...#...#                          ##..#....#.###...#..###..#..#                          #.#.#.#.#.#.#.#.#.#.#.#.#.#.#           
15:           #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#                        ##.####..##.#..#.#####..#######                        #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#          
16:          #...............................#                      ##..#...###..####.#....###......#                      #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#         
17:         #.#.............................#.#                    ##.####.##..###....##..##..#....###                    #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#        
18:        #...#...........................#...#                  ##..#....#.###..#..##.###.####..##..#                  #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#       
19:       #.#.#.#.........................#.#.#.#                ##.####..##.#..######..#...#...###.####                #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#      
20:      #.......#.......................#.......#              ##..#...###..####.....####.###.##...#...#              #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#     
21:     #.#.....#.#.....................#.#.....#.#            ##.####.##..###...#...##....#...#.#.###.###            #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#    
22:    #...#...#...#...................#...#...#...#          ##..#....#.###..#.###.##.#..###.##.#.#...#..#          #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#   
23:   #.#.#.#.#.#.#.#.................#.#.#.#.#.#.#.#        ##.####..##.#..###.#...#..####...#..#.##.######        #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#  
24:  #...............#...............#...............#      ##..#...###..####...##.#####...#.#####.#..#.....#      #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.# 

Tcl

Works with: Tcl version 8.6

<lang tcl>package require Tcl 8.6

oo::class create ElementaryAutomaton {

   variable rules
   # Decode the rule number to get a collection of state mapping rules.
   # In effect, "compiles" the rule number
   constructor {ruleNumber} {

set ins {111 110 101 100 011 010 001 000} set bits [split [string range [format %08b $ruleNumber] end-7 end] ""] foreach input {111 110 101 100 011 010 001 000} state $bits { dict set rules $input $state }

   }
   # Apply the rule to an automaton state to get a new automaton state.
   # We wrap the edges; the state space is circular.
   method evolve {state} {

set len [llength $state] for {set i 0} {$i < $len} {incr i} { lappend result [dict get $rules [ lindex $state [expr {($i-1)%$len}]][ lindex $state $i][ lindex $state [expr {($i+1)%$len}]]] } return $result

   }
   # Simple driver method; omit the initial state to get a centred dot
   method run {steps {initialState ""}} {

if {[llength [info level 0]] < 4} { set initialState "[string repeat . $steps]1[string repeat . $steps]" } set s [split [string map ". 0 # 1" $initialState] ""] for {set i 0} {$i < $steps} {incr i} { puts [string map "0 . 1 #" [join $s ""]] set s [my evolve $s] } puts [string map "0 . 1 #" [join $s ""]]

   }

}</lang> Demonstrating: <lang tcl>puts "Rule 90 (with default state):" ElementaryAutomaton create rule90 90 rule90 run 20 puts "\nRule 122:" [ElementaryAutomaton new 122] run 25 "..........#......…."</lang>

Output:
Rule 90 (with default state):
....................#....................
...................#.#...................
..................#...#..................
.................#.#.#.#.................
................#.......#................
...............#.#.....#.#...............
..............#...#...#...#..............
.............#.#.#.#.#.#.#.#.............
............#...............#............
...........#.#.............#.#...........
..........#...#...........#...#..........
.........#.#.#.#.........#.#.#.#.........
........#.......#.......#.......#........
.......#.#.....#.#.....#.#.....#.#.......
......#...#...#...#...#...#...#...#......
.....#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.....
....#...............................#....
...#.#.............................#.#...
..#...#...........................#...#..
.#.#.#.#.........................#.#.#.#.
#.......#.......................#.......#

Rule 122:
..........#..........
.........#.#.........
........#.#.#........
.......#.#.#.#.......
......#.#.#.#.#......
.....#.#.#.#.#.#.....
....#.#.#.#.#.#.#....
...#.#.#.#.#.#.#.#...
..#.#.#.#.#.#.#.#.#..
.#.#.#.#.#.#.#.#.#.#.
#.#.#.#.#.#.#.#.#.#.#
##.#.#.#.#.#.#.#.#.##
.##.#.#.#.#.#.#.#.##.
####.#.#.#.#.#.#.####
...##.#.#.#.#.#.##...
..####.#.#.#.#.####..
.##..##.#.#.#.##..##.
########.#.#.########
.......##.#.##.......
......####.####......
.....##..###..##.....
....######.######....
...##....###....##...
..####..##.##..####..
.##..###########..##.
######.........######