Elementary cellular automaton/Infinite length: Difference between revisions
m julia example |
m →{{header|Wren}}: Minor tidy |
||
(16 intermediate revisions by 10 users not shown) | |||
Line 1: | Line 1: | ||
{{ |
{{task}} |
||
The purpose of this task is to create a version of an [[Elementary cellular automaton]] whose number of cells is only limited by the memory size of the computer. |
The purpose of this task is to create a version of an [[Elementary cellular automaton]] whose number of cells is only limited by the memory size of the computer. |
||
Line 14: | Line 14: | ||
More complex methods can be imagined, provided it is possible to somehow encode the infinite sections. But for this task we will stick to this simple version. |
More complex methods can be imagined, provided it is possible to somehow encode the infinite sections. But for this task we will stick to this simple version. |
||
=={{header|11l}}== |
|||
{{trans|Nim}} |
|||
<syntaxhighlight lang="11l">F step(cells, rule) |
|||
V result = ‘’ |
|||
L(i) 0 .< cells.len - 2 |
|||
V bin = 0 |
|||
V b = 2 |
|||
L(n) i .< i + 3 |
|||
bin += Int(cells[n] == ‘*’) << b |
|||
b >>= 1 |
|||
V a = I (rule [&] (1 << bin)) != 0 {‘*’} E ‘.’ |
|||
result ‘’= a |
|||
R result |
|||
F addNoCells(&cells) |
|||
V left = I cells[0] == ‘*’ {‘.’} E ‘*’ |
|||
V right = I cells.last == ‘*’ {‘.’} E ‘*’ |
|||
cells = left‘’cells‘’right |
|||
cells = left‘’cells‘’right |
|||
F evolve(limit, rule) |
|||
print(‘Rule #’rule) |
|||
V cells = ‘*’ |
|||
L 0 .< limit |
|||
addNoCells(&cells) |
|||
V width = 40 + (cells.len >> 1) |
|||
print(cells.rjust(width)) |
|||
cells = step(cells, rule) |
|||
evolve(35, 90)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Rule #90 |
|||
..*.. |
|||
..*.*.. |
|||
..*...*.. |
|||
..*.*.*.*.. |
|||
..*.......*.. |
|||
..*.*.....*.*.. |
|||
..*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.. |
|||
..*...............*.. |
|||
..*.*.............*.*.. |
|||
..*...*...........*...*.. |
|||
..*.*.*.*.........*.*.*.*.. |
|||
..*.......*.......*.......*.. |
|||
..*.*.....*.*.....*.*.....*.*.. |
|||
..*...*...*...*...*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. |
|||
..*...............................*.. |
|||
..*.*.............................*.*.. |
|||
..*...*...........................*...*.. |
|||
..*.*.*.*.........................*.*.*.*.. |
|||
..*.......*.......................*.......*.. |
|||
..*.*.....*.*.....................*.*.....*.*.. |
|||
..*...*...*...*...................*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. |
|||
..*...............*...............*...............*.. |
|||
..*.*.............*.*.............*.*.............*.*.. |
|||
..*...*...........*...*...........*...*...........*...*.. |
|||
..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. |
|||
..*.......*.......*.......*.......*.......*.......*.......*.. |
|||
..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. |
|||
..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. |
|||
..*...............................................................*.. |
|||
..*.*.............................................................*.*.. |
|||
..*...*...........................................................*...*.. |
|||
</pre> |
|||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp"> |
||
#include <iostream> |
#include <iostream> |
||
#include <iomanip> |
#include <iomanip> |
||
Line 58: | Line 130: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 91: | Line 163: | ||
=={{header|D}}== |
=={{header|D}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.array, std.range, std.typecons, std.string, std.conv, |
||
std.algorithm; |
std.algorithm; |
||
alias R = replicate; |
alias R = replicate; |
||
Line 115: | Line 187: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
The output is the same as the Python entry. |
The output is the same as the Python entry. |
||
Line 121: | Line 193: | ||
{{works with|Elixir|1.3}} |
{{works with|Elixir|1.3}} |
||
{{trans|Ruby}} |
{{trans|Ruby}} |
||
< |
<syntaxhighlight lang="elixir"> |
||
defmodule Elementary_cellular_automaton do |
defmodule Elementary_cellular_automaton do |
||
def infinite(cell, rule, times) do |
def infinite(cell, rule, times) do |
||
Line 152: | Line 224: | ||
IO.puts "\nRule : #{rule}" |
IO.puts "\nRule : #{rule}" |
||
Elementary_cellular_automaton.infinite("1", rule, 25) |
Elementary_cellular_automaton.infinite("1", rule, 25) |
||
end)</ |
end)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 213: | Line 285: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
{{trans|C++}} |
{{trans|C++}} |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 274: | Line 346: | ||
fmt.Println() |
fmt.Println() |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 340: | Line 412: | ||
First we provide the datatype, the viewer and constructor: |
First we provide the datatype, the viewer and constructor: |
||
< |
<syntaxhighlight lang="haskell">{-# LANGUAGE DeriveFunctor #-} |
||
import Control.Comonad |
import Control.Comonad |
||
Line 352: | Line 424: | ||
fromList [] = fromList [0] |
fromList [] = fromList [0] |
||
fromList (x:xs) = let zeros = Inf.repeat 0 |
fromList (x:xs) = let zeros = Inf.repeat 0 |
||
in Cells zeros x (xs +++ zeros)</ |
in Cells zeros x (xs +++ zeros)</syntaxhighlight> |
||
In order to run the CA on the domain we make it an instance of <code>Comonad</code> class. Running the CA turns to be just an iterative comonadic ''extension'' of the rule: |
In order to run the CA on the domain we make it an instance of <code>Comonad</code> class. Running the CA turns to be just an iterative comonadic ''extension'' of the rule: |
||
< |
<syntaxhighlight lang="haskell">instance Comonad Cells where |
||
extract (Cells _ x _) = x |
extract (Cells _ x _) = x |
||
duplicate x = Cells (rewind left x) x (rewind right x) |
duplicate x = Cells (rewind left x) x (rewind right x) |
||
Line 365: | Line 437: | ||
runCA rule = iterate (=>> step) |
runCA rule = iterate (=>> step) |
||
where step (Cells (l ::: _) x (r ::: _)) = rule l x r</ |
where step (Cells (l ::: _) x (r ::: _)) = rule l x r</syntaxhighlight> |
||
Following is the rule definition and I/O routine: |
Following is the rule definition and I/O routine: |
||
< |
<syntaxhighlight lang="haskell">rule n l x r = n `div` (2^(4*l + 2*x + r)) `mod` 2 |
||
displayCA n w rule init = mapM_ putStrLn $ take n result |
displayCA n w rule init = mapM_ putStrLn $ take n result |
||
where result = fmap display . view w <$> runCA rule init |
where result = fmap display . view w <$> runCA rule init |
||
display 0 = ' ' |
display 0 = ' ' |
||
display _ = '*'</ |
display _ = '*'</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
Line 422: | Line 494: | ||
Implementation: |
Implementation: |
||
< |
<syntaxhighlight lang="j">ext9=: (9#1-{.!.1),],9#1-{:!.1 |
||
trim=: |.@(}.~ ] i. 1-{.)^:2 |
trim=: |.@(}.~ ] i. 1-{.)^:2 |
||
next=: trim@(((8$2) #: [) {~ 2 #. 1 - [: |: |.~"1 0&_1 0 1@]) ext9</ |
next=: trim@(((8$2) #: [) {~ 2 #. 1 - [: |: |.~"1 0&_1 0 1@]) ext9</syntaxhighlight> |
||
In other words, a wrapped version of the [[Elementary_cellular_automaton#J|original implementation]]. |
In other words, a wrapped version of the [[Elementary_cellular_automaton#J|original implementation]]. |
||
Line 430: | Line 502: | ||
example use: |
example use: |
||
< |
<syntaxhighlight lang="j"> ' *'{~90 next^:(i.9) 1 |
||
* |
* |
||
* * |
* * |
||
Line 439: | Line 511: | ||
* * * * |
* * * * |
||
* * * * * * * * |
* * * * * * * * |
||
* *</ |
* *</syntaxhighlight> |
||
Looks like a [[Sierpinski_triangle|Sierpinski triangle]] |
Looks like a [[Sierpinski_triangle|Sierpinski triangle]] |
||
=={{header|Java}}== |
|||
<syntaxhighlight lang="java"> |
|||
public final class ElementaryCellularAutomatonInfiniteLength { |
|||
public static void main(String[] aArgs) { |
|||
evolve(35, 90); |
|||
System.out.println(); |
|||
} |
|||
private static void evolve(int aLimit, int aRule) { |
|||
System.out.println(" Rule# " + aRule); |
|||
StringBuilder cells = new StringBuilder(Character.toString(STAR)); |
|||
for ( int i = 0; i < aLimit; i++ ) { |
|||
addCells(cells); |
|||
final int width = 40 - ( cells.length() >> 1 ); |
|||
System.out.println(" ".repeat(width) + cells); |
|||
cells = nextStep(cells, aRule); |
|||
} |
|||
} |
|||
private static void addCells(StringBuilder aCells) { |
|||
final char left = ( aCells.charAt(0) == STAR ) ? DOT : STAR; |
|||
final char right = ( aCells.charAt(aCells.length() - 1 ) == STAR ) ? DOT : STAR; |
|||
for ( int i = 0; i < 2; i++ ) { |
|||
aCells.insert(0, left); |
|||
aCells.append(right); |
|||
} |
|||
} |
|||
private static StringBuilder nextStep(StringBuilder aCells, int aRule) { |
|||
StringBuilder nextCells = new StringBuilder(); |
|||
for ( int i = 0; i < aCells.length() - 2; i++ ) { |
|||
int binary = 0; |
|||
int shift = 2; |
|||
for ( int j = i; j < i + 3; j++ ) { |
|||
binary += ( ( aCells.charAt(j) == STAR ) ? 1 : 0 ) << shift; |
|||
shift >>= 1; |
|||
} |
|||
final char symbol = ( ( aRule & ( 1 << binary ) ) == 0 ) ? DOT : STAR; |
|||
nextCells.append(symbol); |
|||
} |
|||
return nextCells; |
|||
} |
|||
private static final char DOT = '.'; |
|||
private static final char STAR = '*'; |
|||
} |
|||
</syntaxhighlight> |
|||
{{ out }} |
|||
<pre> |
|||
Rule# 90 |
|||
..*.. |
|||
..*.*.. |
|||
..*...*.. |
|||
..*.*.*.*.. |
|||
..*.......*.. |
|||
..*.*.....*.*.. |
|||
..*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.. |
|||
..*...............*.. |
|||
..*.*.............*.*.. |
|||
..*...*...........*...*.. |
|||
..*.*.*.*.........*.*.*.*.. |
|||
..*.......*.......*.......*.. |
|||
..*.*.....*.*.....*.*.....*.*.. |
|||
..*...*...*...*...*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. |
|||
..*...............................*.. |
|||
..*.*.............................*.*.. |
|||
..*...*...........................*...*.. |
|||
..*.*.*.*.........................*.*.*.*.. |
|||
..*.......*.......................*.......*.. |
|||
..*.*.....*.*.....................*.*.....*.*.. |
|||
..*...*...*...*...................*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. |
|||
..*...............*...............*...............*.. |
|||
..*.*.............*.*.............*.*.............*.*.. |
|||
..*...*...........*...*...........*...*...........*...*.. |
|||
..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. |
|||
..*.......*.......*.......*.......*.......*.......*.......*.. |
|||
..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. |
|||
..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. |
|||
..*...............................................................*.. |
|||
..*.*.............................................................*.*.. |
|||
..*...*...........................................................*...*.. |
|||
</pre> |
|||
=={{header|jq}}== |
|||
'''Adapted from [[#Python|Python]]''' |
|||
{{works with|jq}} |
|||
'''Works with gojq, the Go implementation of jq''' |
|||
'''Preliminaries''' |
|||
<syntaxhighlight lang="jq"> |
|||
def lpad($len; $fill): tostring | ($len - length) as $l | ($fill * $l)[:$l] + .; |
|||
def lpad($len): lpad($len; " "); |
|||
# Like *ix `tr` but it is as though $to is padded with blanks |
|||
def tr($from;$to): |
|||
explode as $s |
|||
| ($from | explode) as $f |
|||
| ($to | explode) as $t |
|||
| reduce range(0;length) as $i ([]; |
|||
($f | index($s[$i])) as $ix |
|||
| if $ix then . + [$t[$ix] // " "] |
|||
else . + [$s[$i]] |
|||
end ) |
|||
| implode; |
|||
# Input: a non-negative integer |
|||
# Output: the corresponding stream of bits (0s and 1s), |
|||
# least significant digit first, with a final 0 |
|||
def stream: |
|||
recurse(if . > 0 then ./2|floor else empty end) | . % 2 ; |
|||
# input: an array, e.g. as produced by [7|stream] |
|||
# output: the corresponding binary string |
|||
def to_b: reverse | map(tostring) | join("") | sub("^0";"");</syntaxhighlight> |
|||
'''The Cellular Automaton''' |
|||
<syntaxhighlight lang="jq"># Output: an unbounded stream of the form [count, row] |
|||
# giving the rows produced by the eca defined by |
|||
# $cells (a string) and $rule (an integer) |
|||
def eca_infinite($cells; $rule): |
|||
def notcell: tr("01";"10") ; |
|||
def rule2hash($rule): |
|||
[$rule | stream] as $r |
|||
| reduce range(0;8) as $i ({}; |
|||
. + { ($i|[stream]|to_b|lpad(3;"0")): ($r[$i] // 0)}); |
|||
rule2hash($rule) as $neighbours2next |
|||
| [0, $cells], |
|||
foreach range(1; infinite) as $i ({c: $cells}; |
|||
.c = (.c[0:1]|notcell)*2 + .c + (.c[-1:]|notcell)*2 # Extend and pad the ends |
|||
| .c = ([range(1; .c|length - 1) as $i | $neighbours2next[.c[$i-1:$i+2] ]] | join("")); |
|||
[$i, .c] ) ; |
|||
</syntaxhighlight> |
|||
'''The Task''' |
|||
<syntaxhighlight lang="jq"># $lines specifies the number of lines to display for each eca |
|||
def main($lines): |
|||
(90, 30) as $rule |
|||
| "\nRule: \($rule)", |
|||
(limit($lines; eca_infinite("1"; $rule) |
|||
| .[0] as $line |
|||
| ($line|lpad(3)) + " " * ($lines - $line) + (.[1] | tr("01"; ".#") ))); |
|||
main(25)</syntaxhighlight> |
|||
{{out}} |
|||
As for [[#Python|Python]]. |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
<syntaxhighlight lang="julia">function ecainfinite(cells, rule, n) |
|||
<lang julia>notcell(cell) = (cell == '1') ? '0' : '1' |
|||
notcell(cell) = (cell == '1') ? '0' : '1' |
|||
rulebits = reverse(string(rule, base = 2, pad = 8)) |
|||
function ecainfinite(cells, rule, n) |
|||
neighbors2next = Dict(string(n - 1, base=2, pad=3) => rulebits[n] for n in 1:8) |
|||
celllength = length(cells) |
|||
rulebits = string(rule, base = 2, pad = 8) |
|||
neighbors2next = Dict(string(n -1, base=2, pad=3) => rulebits[n] for n in 1:8) |
|||
ret = String[] |
ret = String[] |
||
for i in 1:n |
for i in 1:n |
||
Line 462: | Line 685: | ||
function testinfcells(lines::Integer) |
function testinfcells(lines::Integer) |
||
for rule in [90, 30] |
for rule in [90, 30] |
||
println("\nRule: $rule") |
println("\nRule: $rule ($(string(rule, base = 2, pad = 8)))") |
||
s = ecainfinite("1", rule, lines) |
s = ecainfinite("1", rule, lines) |
||
for i in 1:lines |
for i in 1:lines |
||
Line 471: | Line 694: | ||
testinfcells(25) |
testinfcells(25) |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
Rule: 90 |
Rule: 90 (01011010) |
||
1: # |
1: # |
||
2: #.# |
2: #.# |
||
Line 500: | Line 723: | ||
25: #...............#...............#...............# |
25: #...............#...............#...............# |
||
Rule: 30 |
Rule: 30 (00011110) |
||
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: .#### |
16: ##.####..##.#..#.#####..####### |
||
17: |
17: ##..#...###..####.#....###......# |
||
18: |
18: ##.####.##..###....##..##..#....### |
||
19: ##.#####. |
19: ##..#....#.###..#..##.###.####..##..# |
||
20: .#### |
20: ##.####..##.#..######..#...#...###.#### |
||
21: ###..##..# |
21: ##..#...###..####.....####.###.##...#...# |
||
22: |
22: ##.####.##..###...#...##....#...#.#.###.### |
||
23: ##. |
23: ##..#....#.###..#.###.##.#..###.##.#.#...#..# |
||
24: .####.. |
24: ##.####..##.#..###.#...#..####...#..#.##.###### |
||
25: ###..##..#...## |
25: ##..#...###..####...##.#####...#.#####.#..#.....# |
||
</pre> |
</pre> |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|C++}} |
{{trans|C++}} |
||
< |
<syntaxhighlight lang="scala">// version 1.1.51 |
||
fun evolve(l: Int, rule: Int) { |
fun evolve(l: Int, rule: Int) { |
||
Line 570: | Line 793: | ||
evolve(35, 90) |
evolve(35, 90) |
||
println() |
println() |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 611: | Line 834: | ||
..*...*...........................................................*...*.. |
..*...*...........................................................*...*.. |
||
</pre> |
</pre> |
||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
An infinite background is built-in the language: |
|||
<syntaxhighlight lang="mathematica">CellularAutomaton[18, {{1}, 0}, 15] // ArrayPlot |
|||
CellularAutomaton[30, {{1}, 0}, 15] // ArrayPlot</syntaxhighlight> |
|||
=={{header|Nim}}== |
|||
{{trans|Kotlin}} |
|||
<syntaxhighlight lang="nim">import strutils |
|||
func step(cells: string; rule: int): string = |
|||
for i in 0..(cells.len - 3): |
|||
var bin = 0 |
|||
var b = 2 |
|||
for n in i..(i + 2): |
|||
inc bin, ord(cells[n] == '*') shl b |
|||
b = b shr 1 |
|||
let a = if (rule and 1 shl bin) != 0: '*' else: '.' |
|||
result.add(a) |
|||
func addNoCells(cells: var string) = |
|||
let left = if cells[0] == '*': "." else: "*" |
|||
let right = if cells[^1] == '*': "." else: "*" |
|||
cells.insert(left) |
|||
cells.add(right) |
|||
cells.insert(left) |
|||
cells.add(right) |
|||
proc evolve(limit, rule: int) = |
|||
echo "Rule #", rule |
|||
var cells = "*" |
|||
for _ in 0..<limit: |
|||
cells.addNoCells() |
|||
let width = 40 + cells.len shr 1 |
|||
echo cells.align(width) |
|||
cells = cells.step(rule) |
|||
evolve(35, 90)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Rule #90 |
|||
..*.. |
|||
..*.*.. |
|||
..*...*.. |
|||
..*.*.*.*.. |
|||
..*.......*.. |
|||
..*.*.....*.*.. |
|||
..*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.. |
|||
..*...............*.. |
|||
..*.*.............*.*.. |
|||
..*...*...........*...*.. |
|||
..*.*.*.*.........*.*.*.*.. |
|||
..*.......*.......*.......*.. |
|||
..*.*.....*.*.....*.*.....*.*.. |
|||
..*...*...*...*...*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. |
|||
..*...............................*.. |
|||
..*.*.............................*.*.. |
|||
..*...*...........................*...*.. |
|||
..*.*.*.*.........................*.*.*.*.. |
|||
..*.......*.......................*.......*.. |
|||
..*.*.....*.*.....................*.*.....*.*.. |
|||
..*...*...*...*...................*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. |
|||
..*...............*...............*...............*.. |
|||
..*.*.............*.*.............*.*.............*.*.. |
|||
..*...*...........*...*...........*...*...........*...*.. |
|||
..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. |
|||
..*.......*.......*.......*.......*.......*.......*.......*.. |
|||
..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. |
|||
..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. |
|||
..*...............................................................*.. |
|||
..*.*.............................................................*.*.. |
|||
..*...*...........................................................*...*..</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
The edges of a pattern is implicitly repeating. The code will try to lineup output by padding up to 40 spaces to the left, but since the cells keep expanding, that has to end somewhere. |
The edges of a pattern is implicitly repeating. The code will try to lineup output by padding up to 40 spaces to the left, but since the cells keep expanding, that has to end somewhere. |
||
< |
<syntaxhighlight lang="perl">sub evolve { |
||
my ($rule, $pattern) = @_; |
my ($rule, $pattern) = @_; |
||
my $offset = 0; |
my $offset = 0; |
||
Line 635: | Line 938: | ||
} |
} |
||
evolve(90, "010");</ |
evolve(90, "010");</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 652: | Line 955: | ||
-13| ..#.......#.......#.......#.. |
-13| ..#.......#.......#.......#.. |
||
---(infinite more lines snipped)--- |
---(infinite more lines snipped)--- |
||
</pre> |
|||
=={{header|Perl 6}}== |
|||
This version, while it is ''capable'' of working with infinite length cellular automata, makes the assumption that any cells which have not been explicitly examined are in a 'null' state, neither '0' or '1'. Further it makes the assumption that a null cell, on being examined, initially contains nothing (░). Otherwise it would take infinite time to calculate every row and would be exceptionally boring to watch. |
|||
Based heavily on the code from the [[One-dimensional_cellular_automata#Perl_6|One-dimensional cellular automata]] task. Example uses rule 90 (Sierpinski triangle). |
|||
<lang perl6>class Automaton { |
|||
has $.rule; |
|||
has @.cells; |
|||
has @.code = $!rule.fmt('%08b').flip.comb».Int; |
|||
method gist { @!cells.map({+$_ ?? '▲' !! '░'}).join } |
|||
method succ { |
|||
self.new: :$!rule, :@!code, :cells( |
|||
' ', |
|||
|@!code[ |
|||
4 «*« @!cells.rotate(-1) |
|||
»+« 2 «*« @!cells |
|||
»+« @!cells.rotate(1) |
|||
], |
|||
' ' |
|||
) |
|||
} |
|||
} |
|||
my Automaton $a .= new: :rule(90), :cells(flat '010'.comb); |
|||
# display the first 20 rows |
|||
say $a++ for ^20; |
|||
# then calculate the other infinite number of rows, (may take a while) |
|||
$a++ for ^Inf;</lang> |
|||
{{out}} |
|||
<pre>░▲░ |
|||
░▲░▲░ |
|||
░▲░░░▲░ |
|||
░▲░▲░▲░▲░ |
|||
░▲░░░░░░░▲░ |
|||
░▲░▲░░░░░▲░▲░ |
|||
░▲░░░▲░░░▲░░░▲░ |
|||
░▲░▲░▲░▲░▲░▲░▲░▲░ |
|||
░▲░░░░░░░░░░░░░░░▲░ |
|||
░▲░▲░░░░░░░░░░░░░▲░▲░ |
|||
░▲░░░▲░░░░░░░░░░░▲░░░▲░ |
|||
░▲░▲░▲░▲░░░░░░░░░▲░▲░▲░▲░ |
|||
░▲░░░░░░░▲░░░░░░░▲░░░░░░░▲░ |
|||
░▲░▲░░░░░▲░▲░░░░░▲░▲░░░░░▲░▲░ |
|||
░▲░░░▲░░░▲░░░▲░░░▲░░░▲░░░▲░░░▲░ |
|||
░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░ |
|||
░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░ |
|||
░▲░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░▲░ |
|||
░▲░░░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░░░▲░ |
|||
░▲░▲░▲░▲░░░░░░░░░░░░░░░░░░░░░░░░░▲░▲░▲░▲░ |
|||
^C |
|||
</pre> |
</pre> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Uses 0-expansion either side |
Uses 0-expansion either side |
||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<lang Phix>string s = ".#.", |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
t=s, r = "........" |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">".#."</span><span style="color: #0000FF;">,</span> |
|||
integer rule = 18, k, l = length(s), w = 0 |
|||
<span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"........"</span> |
|||
for i=1 to 8 do |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">rule</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">18</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
r[i] = iff(mod(rule,2)?'#':'.') |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span> |
|||
rule = floor(rule/2) |
|||
<span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)?</span><span style="color: #008000;">'#'</span><span style="color: #0000FF;">:</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">)</span> |
|||
end for |
|||
<span style="color: #000000;">rule</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rule</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> |
|||
for i=0 to 25 do |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
?repeat(' ',floor((55-length(s))/2))&s |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">25</span> <span style="color: #008080;">do</span> |
|||
for j=1 to l do |
|||
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">55</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">))/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">))&</span><span style="color: #000000;">s</span> |
|||
k = (s[iff(j=1?l:j-1)]='#')*4 |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span> |
|||
+ (s[ j ]='#')*2 |
|||
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #000000;">l</span><span style="color: #0000FF;">:</span><span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)]=</span><span style="color: #008000;">'#'</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">4</span> |
|||
+ (s[iff(j=l?1:j+1)]='#')+1 |
|||
<span style="color: #0000FF;">+</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span> <span style="color: #000000;">j</span> <span style="color: #0000FF;">]=</span><span style="color: #008000;">'#'</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">2</span> |
|||
t[j] = r[k] |
|||
<span style="color: #0000FF;">+</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">l</span><span style="color: #0000FF;">?</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)]=</span><span style="color: #008000;">'#'</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span> |
|||
end for |
|||
<span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> |
|||
if t[1]='#' then t = '.'&t end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
if t[$]='#' then t = t&'.' end if |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'#'</span> <span style="color: #008080;">then</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'.'</span><span style="color: #0000FF;">&</span><span style="color: #000000;">t</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
l = length(t) |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">[$]=</span><span style="color: #008000;">'#'</span> <span style="color: #008080;">then</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">&</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
s = t |
|||
<span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span> |
|||
end for</lang> |
|||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 765: | Line 1,015: | ||
Infinite generator but only print 25 lines of each rule. |
Infinite generator but only print 25 lines of each rule. |
||
< |
<syntaxhighlight lang="python">def _notcell(c): |
||
return '0' if c == '1' else '1' |
return '0' if c == '1' else '1' |
||
Line 785: | Line 1,035: | ||
print('\nRule: %i' % rule) |
print('\nRule: %i' % rule) |
||
for i, c in zip(range(lines), eca_infinite('1', rule)): |
for i, c in zip(range(lines), eca_infinite('1', rule)): |
||
print('%2i: %s%s' % (i, ' '*(lines - i), c.replace('0', '.').replace('1', '#')))</ |
print('%2i: %s%s' % (i, ' '*(lines - i), c.replace('0', '.').replace('1', '#')))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 846: | Line 1,096: | ||
Uses solution to [[Elementary cellular automaton]] saved in file "Elementary_cellular_automata.rkt" |
Uses solution to [[Elementary cellular automaton]] saved in file "Elementary_cellular_automata.rkt" |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
; below is the code from the parent task |
; below is the code from the parent task |
||
(require "Elementary_cellular_automata.rkt") |
(require "Elementary_cellular_automata.rkt") |
||
Line 878: | Line 1,128: | ||
(show-automaton v #:step step #:push-right o) |
(show-automaton v #:step step #:push-right o) |
||
(newline) |
(newline) |
||
(ng/90/infinite v o)))</ |
(ng/90/infinite v o)))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 924: | Line 1,174: | ||
#fx(536879104 0 33554944) |
#fx(536879104 0 33554944) |
||
0</pre> |
0</pre> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
This version, while it is ''capable'' of working with infinite length cellular automata, makes the assumption that any cells which have not been explicitly examined are in a 'null' state, neither '0' or '1'. Further it makes the assumption that a null cell, on being examined, initially contains nothing (░). Otherwise it would take infinite time to calculate every row and would be exceptionally boring to watch. |
|||
Based heavily on the code from the [[One-dimensional_cellular_automata#Raku|One-dimensional cellular automata]] task. Example uses rule 90 (Sierpinski triangle). |
|||
<syntaxhighlight lang="raku" line>class Automaton { |
|||
has $.rule; |
|||
has @.cells; |
|||
has @.code = $!rule.fmt('%08b').flip.comb».Int; |
|||
method gist { @!cells.map({+$_ ?? '▲' !! '░'}).join } |
|||
method succ { |
|||
self.new: :$!rule, :@!code, :cells( |
|||
' ', |
|||
|@!code[ |
|||
4 «*« @!cells.rotate(-1) |
|||
»+« 2 «*« @!cells |
|||
»+« @!cells.rotate(1) |
|||
], |
|||
' ' |
|||
) |
|||
} |
|||
} |
|||
my Automaton $a .= new: :rule(90), :cells(flat '010'.comb); |
|||
# display the first 20 rows |
|||
say $a++ for ^20; |
|||
# then calculate the other infinite number of rows, (may take a while) |
|||
$a++ for ^Inf;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>░▲░ |
|||
░▲░▲░ |
|||
░▲░░░▲░ |
|||
░▲░▲░▲░▲░ |
|||
░▲░░░░░░░▲░ |
|||
░▲░▲░░░░░▲░▲░ |
|||
░▲░░░▲░░░▲░░░▲░ |
|||
░▲░▲░▲░▲░▲░▲░▲░▲░ |
|||
░▲░░░░░░░░░░░░░░░▲░ |
|||
░▲░▲░░░░░░░░░░░░░▲░▲░ |
|||
░▲░░░▲░░░░░░░░░░░▲░░░▲░ |
|||
░▲░▲░▲░▲░░░░░░░░░▲░▲░▲░▲░ |
|||
░▲░░░░░░░▲░░░░░░░▲░░░░░░░▲░ |
|||
░▲░▲░░░░░▲░▲░░░░░▲░▲░░░░░▲░▲░ |
|||
░▲░░░▲░░░▲░░░▲░░░▲░░░▲░░░▲░░░▲░ |
|||
░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░ |
|||
░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░ |
|||
░▲░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░▲░ |
|||
░▲░░░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░░░▲░ |
|||
░▲░▲░▲░▲░░░░░░░░░░░░░░░░░░░░░░░░░▲░▲░▲░▲░ |
|||
^C |
|||
</pre> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="ruby">def notcell(c) |
||
c.tr('01','10') |
c.tr('01','10') |
||
end |
end |
||
Line 951: | Line 1,258: | ||
end |
end |
||
end |
end |
||
end</ |
end</syntaxhighlight> |
||
The output is the same as the Python entry. |
The output is the same as the Python entry. |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
{{trans|Perl}} |
{{trans|Perl}} |
||
< |
<syntaxhighlight lang="ruby">func evolve(rule, bin) { |
||
var offset = 0 |
var offset = 0 |
||
var (l='', r='') |
var (l='', r='') |
||
Line 969: | Line 1,276: | ||
} |
} |
||
evolve(90, "010")</ |
evolve(90, "010")</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 997: | Line 1,304: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{works with|Tcl|8.6}} |
{{works with|Tcl|8.6}} |
||
< |
<syntaxhighlight lang="tcl">package require Tcl 8.6 |
||
oo::class create InfiniteElementaryAutomaton { |
oo::class create InfiniteElementaryAutomaton { |
||
Line 1,052: | Line 1,359: | ||
$rule run 25 |
$rule run 25 |
||
$rule destroy |
$rule destroy |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,109: | Line 1,416: | ||
….##..#...###..####...##.#####...#.#####.#..#.....#.… |
….##..#...###..####...##.#####...#.#####.#..#.....#.… |
||
.##.####.##..###...#.##..#....#.##.#.....#####...###. |
.##.####.##..###...#.##..#....#.##.#.....#####...###. |
||
</pre> |
|||
=={{header|Wren}}== |
|||
{{trans|Kotlin}} |
|||
{{libheader|Wren-fmt}} |
|||
<syntaxhighlight lang="wren">import "./fmt" for Fmt |
|||
var addNoCells = Fn.new { |s| |
|||
var l = (s[0] == "*") ? "." : "*" |
|||
var r = (s[-1] == "*") ? "." : "*" |
|||
for (i in 0..1) { |
|||
s.insert(0, l) |
|||
s.add(r) |
|||
} |
|||
} |
|||
var step = Fn.new { |cells, rule| |
|||
var newCells = [] |
|||
for (i in 0...cells.count - 2) { |
|||
var bin = 0 |
|||
var b = 2 |
|||
for (n in i...i + 3) { |
|||
bin = bin + (((cells[n] == "*") ? 1 : 0) << b) |
|||
b = b >> 1 |
|||
} |
|||
var a = ((rule & (1 << bin)) != 0) ? "*" : "." |
|||
newCells.add(a) |
|||
} |
|||
return newCells |
|||
} |
|||
var evolve = Fn.new { |l, rule| |
|||
System.print(" Rule #%(rule):") |
|||
var cells = ["*"] |
|||
for (x in 0...l) { |
|||
addNoCells.call(cells) |
|||
var width = 40 + (cells.count >> 1) |
|||
Fmt.print("$*s", width, cells.join()) |
|||
cells = step.call(cells, rule) |
|||
} |
|||
} |
|||
evolve.call(35, 90) |
|||
System.print()</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Rule #90: |
|||
..*.. |
|||
..*.*.. |
|||
..*...*.. |
|||
..*.*.*.*.. |
|||
..*.......*.. |
|||
..*.*.....*.*.. |
|||
..*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.. |
|||
..*...............*.. |
|||
..*.*.............*.*.. |
|||
..*...*...........*...*.. |
|||
..*.*.*.*.........*.*.*.*.. |
|||
..*.......*.......*.......*.. |
|||
..*.*.....*.*.....*.*.....*.*.. |
|||
..*...*...*...*...*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. |
|||
..*...............................*.. |
|||
..*.*.............................*.*.. |
|||
..*...*...........................*...*.. |
|||
..*.*.*.*.........................*.*.*.*.. |
|||
..*.......*.......................*.......*.. |
|||
..*.*.....*.*.....................*.*.....*.*.. |
|||
..*...*...*...*...................*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. |
|||
..*...............*...............*...............*.. |
|||
..*.*.............*.*.............*.*.............*.*.. |
|||
..*...*...........*...*...........*...*...........*...*.. |
|||
..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. |
|||
..*.......*.......*.......*.......*.......*.......*.......*.. |
|||
..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. |
|||
..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. |
|||
..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. |
|||
..*...............................................................*.. |
|||
..*.*.............................................................*.*.. |
|||
..*...*...........................................................*...*.. |
|||
</pre> |
</pre> |
||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
{{trans|D}} |
{{trans|D}} |
||
< |
<syntaxhighlight lang="zkl">nLines,flipCell := 25, fcn(c){ (c=="1") and "0" or "1" }; |
||
foreach rule in (T(90,30)){ |
foreach rule in (T(90,30)){ |
||
println("\nRule: ", rule); |
println("\nRule: ", rule); |
||
Line 1,125: | Line 1,515: | ||
C=[1..C.len()-2].pump(String,'wrap(n){ neighs2next[C[n-1,3]] }); |
C=[1..C.len()-2].pump(String,'wrap(n){ neighs2next[C[n-1,3]] }); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
Latest revision as of 16:32, 28 November 2023
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
The purpose of this task is to create a version of an Elementary cellular automaton whose number of cells is only limited by the memory size of the computer.
To be precise, consider the state of the automaton to be made of an infinite number of cells, but with a bounded support. In other words, to describe the state of the automaton, you need a finite number of adjacent cells, along with their individual state, and you then consider that the individual state of each of all other cells is the negation of the closest individual cell among the previously defined finite number of cells.
Examples:
1 -> ..., 0, 0, 1, 0, 0, ... 0, 1 -> ..., 1, 1, 0, 1, 0, 0, ... 1, 0, 1 -> ..., 0, 0, 1, 0, 1, 0, 0, ...
More complex methods can be imagined, provided it is possible to somehow encode the infinite sections. But for this task we will stick to this simple version.
11l
F step(cells, rule)
V result = ‘’
L(i) 0 .< cells.len - 2
V bin = 0
V b = 2
L(n) i .< i + 3
bin += Int(cells[n] == ‘*’) << b
b >>= 1
V a = I (rule [&] (1 << bin)) != 0 {‘*’} E ‘.’
result ‘’= a
R result
F addNoCells(&cells)
V left = I cells[0] == ‘*’ {‘.’} E ‘*’
V right = I cells.last == ‘*’ {‘.’} E ‘*’
cells = left‘’cells‘’right
cells = left‘’cells‘’right
F evolve(limit, rule)
print(‘Rule #’rule)
V cells = ‘*’
L 0 .< limit
addNoCells(&cells)
V width = 40 + (cells.len >> 1)
print(cells.rjust(width))
cells = step(cells, rule)
evolve(35, 90)
- Output:
Rule #90 ..*.. ..*.*.. ..*...*.. ..*.*.*.*.. ..*.......*.. ..*.*.....*.*.. ..*...*...*...*.. ..*.*.*.*.*.*.*.*.. ..*...............*.. ..*.*.............*.*.. ..*...*...........*...*.. ..*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................*.. ..*.*.............................*.*.. ..*...*...........................*...*.. ..*.*.*.*.........................*.*.*.*.. ..*.......*.......................*.......*.. ..*.*.....*.*.....................*.*.....*.*.. ..*...*...*...*...................*...*...*...*.. ..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. ..*...............*...............*...............*.. ..*.*.............*.*.............*.*.............*.*.. ..*...*...........*...*...........*...*...........*...*.. ..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.......*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................................................*.. ..*.*.............................................................*.*.. ..*...*...........................................................*...*..
C++
#include <iostream>
#include <iomanip>
#include <string>
class oo {
public:
void evolve( int l, int rule ) {
std::string cells = "O";
std::cout << " Rule #" << rule << ":\n";
for( int x = 0; x < l; x++ ) {
addNoCells( cells );
std::cout << std::setw( 40 + ( static_cast<int>( cells.length() ) >> 1 ) ) << cells << "\n";
step( cells, rule );
}
}
private:
void step( std::string& cells, int rule ) {
int bin;
std::string newCells;
for( size_t i = 0; i < cells.length() - 2; i++ ) {
bin = 0;
for( size_t n = i, b = 2; n < i + 3; n++, b >>= 1 ) {
bin += ( ( cells[n] == 'O' ? 1 : 0 ) << b );
}
newCells.append( 1, rule & ( 1 << bin ) ? 'O' : '.' );
}
cells = newCells;
}
void addNoCells( std::string& s ) {
char l = s.at( 0 ) == 'O' ? '.' : 'O',
r = s.at( s.length() - 1 ) == 'O' ? '.' : 'O';
s = l + s + r;
s = l + s + r;
}
};
int main( int argc, char* argv[] ) {
oo o;
o.evolve( 35, 90 );
std::cout << "\n";
return 0;
}
- Output:
Rule #90: Rule #30: ..O.. ..O.. ..O.O.. ..OOO.. ..O...O.. ..OO..O.. ..O.O.O.O.. ..OO.OOOO.. ..O.......O.. ..OO..O...O.. ..O.O.....O.O.. ..OO.OOOO.OOO.. ..O...O...O...O.. ..OO..O....O..O.. ..O.O.O.O.O.O.O.O.. ..OO.OOOO..OOOOOO.. ..O...............O.. ..OO..O...OOO.....O.. ..O.O.............O.O.. ..OO.OOOO.OO..O...OOO.. ..O...O...........O...O.. ..OO..O....O.OOOO.OO..O.. ..O.O.O.O.........O.O.O.O.. ..OO.OOOO..OO.O....O.OOOO.. ..O.......O.......O.......O.. ..OO..O...OOO..OO..OO.O...O.. ..O.O.....O.O.....O.O.....O.O.. ..OO.OOOO.OO..OOO.OOO..OO.OOO.. ..O...O...O...O...O...O...O...O.. ..OO..O....O.OOO...O..OOO..O..O.. ..O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.. ..OO.OOOO..OO.O..O.OOOOO..OOOOOOO.. ..O...............................O.. ..OO..O...OOO..OOOO.O....OOO......O.. ..O.O.............................O.O.. ..OO.OOOO.OO..OOO....OO..OO..O....OOO.. ..O...O...........................O...O.. ..OO..O....O.OOO..O..OO.OOO.OOOO..OO..O.. ..O.O.O.O.........................O.O.O.O.. ..OO.OOOO..OO.O..OOOOOO..O...O...OOO.OOOO.. ..O.......O.......................O.......O.. ..OO..O...OOO..OOOO.....OOOO.OOO.OO...O...O.. ..O.O.....O.O.....................O.O.....O.O.. ..OO.OOOO.OO..OOO...O...OO....O...O.O.OOO.OOO.. ..O...O...O...O...................O...O...O...O.. ..OO..O....O.OOO..O.OOO.OO.O..OOO.OO.O.O...O..O.. ..O.O.O.O.O.O.O.O.................O.O.O.O.O.O.O.O.. ..OO.OOOO..OO.O..OOO.O...O..OOOO...O..O.OO.OOOOOO.. ..O...............O...............O...............O.. ..OO..O...OOO..OOOO...OO.OOOOO...O.OOOOO.O..O.....O..
D
import std.stdio, std.array, std.range, std.typecons, std.string, std.conv,
std.algorithm;
alias R = replicate;
void main() {
enum nLines = 25;
enum notCell = (in char c) pure => (c == '1') ? "0" : "1";
foreach (immutable rule; [90, 30]) {
writeln("\nRule: ", rule);
immutable ruleBits = "%08b".format(rule).retro.text;
const neighs2next = 8.iota
.map!(n => tuple("%03b".format(n), [ruleBits[n]]))
.assocArray;
string C = "1";
foreach (immutable i; 0 .. nLines) {
writefln("%2d: %s%s", i, " ".R(nLines - i), C.tr("01", ".#"));
C = notCell(C[0]).R(2) ~ C ~ notCell(C[$ - 1]).R(2);
C = iota(1, C.length - 1)
.map!(i => neighs2next[C[i - 1 .. i + 2]])
.join;
}
}
}
The output is the same as the Python entry.
Elixir
defmodule Elementary_cellular_automaton do
def infinite(cell, rule, times) do
each(cell, rule_pattern(rule), times)
end
defp each(_, _, 0), do: :ok
defp each(cells, rules, times) do
IO.write String.duplicate(" ", times)
IO.puts String.replace(cells, "0", ".") |> String.replace("1", "#")
c = not_cell(String.first(cells)) <> cells <> not_cell(String.last(cells))
next_cells = Enum.map_join(0..String.length(cells)+1, fn i ->
Map.get(rules, String.slice(c, i, 3))
end)
each(next_cells, rules, times-1)
end
defp not_cell("0"), do: "11"
defp not_cell("1"), do: "00"
defp rule_pattern(rule) do
list = Integer.to_string(rule, 2) |> String.pad_leading(8, "0")
|> String.codepoints |> Enum.reverse
Enum.map(0..7, fn i -> Integer.to_string(i, 2) |> String.pad_leading(3, "0") end)
|> Enum.zip(list) |> Map.new
end
end
Enum.each([18, 30], fn rule ->
IO.puts "\nRule : #{rule}"
Elementary_cellular_automaton.infinite("1", rule, 25)
end)
- Output:
Rule : 18 # #.# #...# #.#.#.# #.......# #.#.....#.# #...#...#...# #.#.#.#.#.#.#.# #...............# #.#.............#.# #...#...........#...# #.#.#.#.........#.#.#.# #.......#.......#.......# #.#.....#.#.....#.#.....#.# #...#...#...#...#...#...#...# #.#.#.#.#.#.#.#.#.#.#.#.#.#.#.# #...............................# #.#.............................#.# #...#...........................#...# #.#.#.#.........................#.#.#.# #.......#.......................#.......# #.#.....#.#.....................#.#.....#.# #...#...#...#...................#...#...#...# #.#.#.#.#.#.#.#.................#.#.#.#.#.#.#.# #...............#...............#...............# Rule : 30 # ### ##..# ##.#### ##..#...# ##.####.### ##..#....#..# ##.####..###### ##..#...###.....# ##.####.##..#...### ##..#....#.####.##..# ##.####..##.#....#.#### ##..#...###..##..##.#...# ##.####.##..###.###..##.### ##..#....#.###...#..###..#..# ##.####..##.#..#.#####..####### ##..#...###..####.#....###......# ##.####.##..###....##..##..#....### ##..#....#.###..#..##.###.####..##..# ##.####..##.#..######..#...#...###.#### ##..#...###..####.....####.###.##...#...# ##.####.##..###...#...##....#...#.#.###.### ##..#....#.###..#.###.##.#..###.##.#.#...#..# ##.####..##.#..###.#...#..####...#..#.##.###### ##..#...###..####...##.#####...#.#####.#..#.....#
Go
package main
import (
"fmt"
"strings"
)
func btoi(b bool) int {
if b {
return 1
}
return 0
}
func evolve(l, rule int) {
fmt.Printf(" Rule #%d:\n", rule)
cells := "O"
for x := 0; x < l; x++ {
cells = addNoCells(cells)
width := 40 + (len(cells) >> 1)
fmt.Printf("%*s\n", width, cells)
cells = step(cells, rule)
}
}
func step(cells string, rule int) string {
newCells := new(strings.Builder)
for i := 0; i < len(cells)-2; i++ {
bin := 0
b := uint(2)
for n := i; n < i+3; n++ {
bin += btoi(cells[n] == 'O') << b
b >>= 1
}
a := '.'
if rule&(1<<uint(bin)) != 0 {
a = 'O'
}
newCells.WriteRune(a)
}
return newCells.String()
}
func addNoCells(cells string) string {
l, r := "O", "O"
if cells[0] == 'O' {
l = "."
}
if cells[len(cells)-1] == 'O' {
r = "."
}
cells = l + cells + r
cells = l + cells + r
return cells
}
func main() {
for _, r := range []int{90, 30} {
evolve(25, r)
fmt.Println()
}
}
- Output:
Rule #90: ..O.. ..O.O.. ..O...O.. ..O.O.O.O.. ..O.......O.. ..O.O.....O.O.. ..O...O...O...O.. ..O.O.O.O.O.O.O.O.. ..O...............O.. ..O.O.............O.O.. ..O...O...........O...O.. ..O.O.O.O.........O.O.O.O.. ..O.......O.......O.......O.. ..O.O.....O.O.....O.O.....O.O.. ..O...O...O...O...O...O...O...O.. ..O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.. ..O...............................O.. ..O.O.............................O.O.. ..O...O...........................O...O.. ..O.O.O.O.........................O.O.O.O.. ..O.......O.......................O.......O.. ..O.O.....O.O.....................O.O.....O.O.. ..O...O...O...O...................O...O...O...O.. ..O.O.O.O.O.O.O.O.................O.O.O.O.O.O.O.O.. ..O...............O...............O...............O.. Rule #30: ..O.. ..OOO.. ..OO..O.. ..OO.OOOO.. ..OO..O...O.. ..OO.OOOO.OOO.. ..OO..O....O..O.. ..OO.OOOO..OOOOOO.. ..OO..O...OOO.....O.. ..OO.OOOO.OO..O...OOO.. ..OO..O....O.OOOO.OO..O.. ..OO.OOOO..OO.O....O.OOOO.. ..OO..O...OOO..OO..OO.O...O.. ..OO.OOOO.OO..OOO.OOO..OO.OOO.. ..OO..O....O.OOO...O..OOO..O..O.. ..OO.OOOO..OO.O..O.OOOOO..OOOOOOO.. ..OO..O...OOO..OOOO.O....OOO......O.. ..OO.OOOO.OO..OOO....OO..OO..O....OOO.. ..OO..O....O.OOO..O..OO.OOO.OOOO..OO..O.. ..OO.OOOO..OO.O..OOOOOO..O...O...OOO.OOOO.. ..OO..O...OOO..OOOO.....OOOO.OOO.OO...O...O.. ..OO.OOOO.OO..OOO...O...OO....O...O.O.OOO.OOO.. ..OO..O....O.OOO..O.OOO.OO.O..OOO.OO.O.O...O..O.. ..OO.OOOO..OO.O..OOO.O...O..OOOO...O..O.OO.OOOOOO.. ..OO..O...OOO..OOOO...OO.OOOOO...O.OOOOO.O..O.....O..
Haskell
Infinite lists are natural in Haskell, however the task forces us to deal with lists that are infinite in both directions. These structures could be efficiently implemented as a zipper lists. Moreover, zipper lists are instances of magic Comonad
class, which gives beautifull implementation of cellular automata.
This solution is kinda involved, but it is guaranteed to be total and correct by type checker.
First we provide the datatype, the viewer and constructor:
{-# LANGUAGE DeriveFunctor #-}
import Control.Comonad
import Data.InfList (InfList (..), (+++))
import qualified Data.InfList as Inf
data Cells a = Cells (InfList a) a (InfList a) deriving Functor
view n (Cells l x r) = reverse (Inf.take n l) ++ [x] ++ (Inf.take n r)
fromList [] = fromList [0]
fromList (x:xs) = let zeros = Inf.repeat 0
in Cells zeros x (xs +++ zeros)
In order to run the CA on the domain we make it an instance of Comonad
class. Running the CA turns to be just an iterative comonadic extension of the rule:
instance Comonad Cells where
extract (Cells _ x _) = x
duplicate x = Cells (rewind left x) x (rewind right x)
where
rewind dir = Inf.iterate dir . dir
right (Cells l x (r ::: rs)) = Cells (x ::: l) r rs
left (Cells (l ::: ls) x r) = Cells ls l (x ::: r)
runCA rule = iterate (=>> step)
where step (Cells (l ::: _) x (r ::: _)) = rule l x r
Following is the rule definition and I/O routine:
rule n l x r = n `div` (2^(4*l + 2*x + r)) `mod` 2
displayCA n w rule init = mapM_ putStrLn $ take n result
where result = fmap display . view w <$> runCA rule init
display 0 = ' '
display _ = '*'
- Output:
λ> displayCA 30 20 (rule 90) (fromList [1]) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
See also Elementary cellular automaton#Haskell
J
Implementation note: edges are complement of the first and last represented cell, which we define as 1 for the case of an empty numeric list. (So we can represent an infinite space of 0s but not an infinite space of 1s.)
We actually only extend our edges by 9 positions (which is more than sufficient), and then trim everything up to the first change from each edge (so the result from a rule which results in all 1s will be silently converted to an empty all 0s result).
Note however that this means that positions in the result are not anchored to positions in the argument. They might correspond or they might be "off by one" position.
Implementation:
ext9=: (9#1-{.!.1),],9#1-{:!.1
trim=: |.@(}.~ ] i. 1-{.)^:2
next=: trim@(((8$2) #: [) {~ 2 #. 1 - [: |: |.~"1 0&_1 0 1@]) ext9
In other words, a wrapped version of the original implementation.
example use:
' *'{~90 next^:(i.9) 1
*
* *
* *
* * * *
* *
* * * *
* * * *
* * * * * * * *
* *
Looks like a Sierpinski triangle
Java
public final class ElementaryCellularAutomatonInfiniteLength {
public static void main(String[] aArgs) {
evolve(35, 90);
System.out.println();
}
private static void evolve(int aLimit, int aRule) {
System.out.println(" Rule# " + aRule);
StringBuilder cells = new StringBuilder(Character.toString(STAR));
for ( int i = 0; i < aLimit; i++ ) {
addCells(cells);
final int width = 40 - ( cells.length() >> 1 );
System.out.println(" ".repeat(width) + cells);
cells = nextStep(cells, aRule);
}
}
private static void addCells(StringBuilder aCells) {
final char left = ( aCells.charAt(0) == STAR ) ? DOT : STAR;
final char right = ( aCells.charAt(aCells.length() - 1 ) == STAR ) ? DOT : STAR;
for ( int i = 0; i < 2; i++ ) {
aCells.insert(0, left);
aCells.append(right);
}
}
private static StringBuilder nextStep(StringBuilder aCells, int aRule) {
StringBuilder nextCells = new StringBuilder();
for ( int i = 0; i < aCells.length() - 2; i++ ) {
int binary = 0;
int shift = 2;
for ( int j = i; j < i + 3; j++ ) {
binary += ( ( aCells.charAt(j) == STAR ) ? 1 : 0 ) << shift;
shift >>= 1;
}
final char symbol = ( ( aRule & ( 1 << binary ) ) == 0 ) ? DOT : STAR;
nextCells.append(symbol);
}
return nextCells;
}
private static final char DOT = '.';
private static final char STAR = '*';
}
- Output:
Rule# 90 ..*.. ..*.*.. ..*...*.. ..*.*.*.*.. ..*.......*.. ..*.*.....*.*.. ..*...*...*...*.. ..*.*.*.*.*.*.*.*.. ..*...............*.. ..*.*.............*.*.. ..*...*...........*...*.. ..*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................*.. ..*.*.............................*.*.. ..*...*...........................*...*.. ..*.*.*.*.........................*.*.*.*.. ..*.......*.......................*.......*.. ..*.*.....*.*.....................*.*.....*.*.. ..*...*...*...*...................*...*...*...*.. ..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. ..*...............*...............*...............*.. ..*.*.............*.*.............*.*.............*.*.. ..*...*...........*...*...........*...*...........*...*.. ..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.......*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................................................*.. ..*.*.............................................................*.*.. ..*...*...........................................................*...*..
jq
Adapted from Python
Works with gojq, the Go implementation of jq
Preliminaries
def lpad($len; $fill): tostring | ($len - length) as $l | ($fill * $l)[:$l] + .;
def lpad($len): lpad($len; " ");
# Like *ix `tr` but it is as though $to is padded with blanks
def tr($from;$to):
explode as $s
| ($from | explode) as $f
| ($to | explode) as $t
| reduce range(0;length) as $i ([];
($f | index($s[$i])) as $ix
| if $ix then . + [$t[$ix] // " "]
else . + [$s[$i]]
end )
| implode;
# Input: a non-negative integer
# Output: the corresponding stream of bits (0s and 1s),
# least significant digit first, with a final 0
def stream:
recurse(if . > 0 then ./2|floor else empty end) | . % 2 ;
# input: an array, e.g. as produced by [7|stream]
# output: the corresponding binary string
def to_b: reverse | map(tostring) | join("") | sub("^0";"");
The Cellular Automaton
# Output: an unbounded stream of the form [count, row]
# giving the rows produced by the eca defined by
# $cells (a string) and $rule (an integer)
def eca_infinite($cells; $rule):
def notcell: tr("01";"10") ;
def rule2hash($rule):
[$rule | stream] as $r
| reduce range(0;8) as $i ({};
. + { ($i|[stream]|to_b|lpad(3;"0")): ($r[$i] // 0)});
rule2hash($rule) as $neighbours2next
| [0, $cells],
foreach range(1; infinite) as $i ({c: $cells};
.c = (.c[0:1]|notcell)*2 + .c + (.c[-1:]|notcell)*2 # Extend and pad the ends
| .c = ([range(1; .c|length - 1) as $i | $neighbours2next[.c[$i-1:$i+2] ]] | join(""));
[$i, .c] ) ;
The Task
# $lines specifies the number of lines to display for each eca
def main($lines):
(90, 30) as $rule
| "\nRule: \($rule)",
(limit($lines; eca_infinite("1"; $rule)
| .[0] as $line
| ($line|lpad(3)) + " " * ($lines - $line) + (.[1] | tr("01"; ".#") )));
main(25)
- Output:
As for Python.
Julia
function ecainfinite(cells, rule, n)
notcell(cell) = (cell == '1') ? '0' : '1'
rulebits = reverse(string(rule, base = 2, pad = 8))
neighbors2next = Dict(string(n - 1, base=2, pad=3) => rulebits[n] for n in 1:8)
ret = String[]
for i in 1:n
push!(ret, cells)
cells = notcell(cells[1])^2 * cells * notcell(cells[end])^2 # Extend/pad ends
cells = join([neighbors2next[cells[i:i+2]] for i in 1:length(cells)-2], "")
end
ret
end
function testinfcells(lines::Integer)
for rule in [90, 30]
println("\nRule: $rule ($(string(rule, base = 2, pad = 8)))")
s = ecainfinite("1", rule, lines)
for i in 1:lines
println("$i: ", " "^(lines - i), replace(replace(s[i], "0" => "."), "1" => "#"))
end
end
end
testinfcells(25)
- Output:
Rule: 90 (01011010) 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: #...............#...............#...............# Rule: 30 (00011110) 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: ##..#...###..####...##.#####...#.#####.#..#.....#
Kotlin
// version 1.1.51
fun evolve(l: Int, rule: Int) {
println(" Rule #$rule:")
var cells = StringBuilder("*")
for (x in 0 until l) {
addNoCells(cells)
val width = 40 + (cells.length shr 1)
println(cells.padStart(width))
cells = step(cells, rule)
}
}
fun step(cells: StringBuilder, rule: Int): StringBuilder {
val newCells = StringBuilder()
for (i in 0 until cells.length - 2) {
var bin = 0
var b = 2
for (n in i until i + 3) {
bin += (if (cells[n] == '*') 1 else 0) shl b
b = b shr 1
}
val a = if ((rule and (1 shl bin)) != 0) '*' else '.'
newCells.append(a)
}
return newCells
}
fun addNoCells(s: StringBuilder) {
val l = if (s[0] == '*') '.' else '*'
val r = if (s[s.length - 1] == '*') '.' else '*'
repeat(2) {
s.insert(0, l)
s.append(r)
}
}
fun main(args: Array<String>) {
evolve(35, 90)
println()
}
- Output:
Rule #90: ..*.. ..*.*.. ..*...*.. ..*.*.*.*.. ..*.......*.. ..*.*.....*.*.. ..*...*...*...*.. ..*.*.*.*.*.*.*.*.. ..*...............*.. ..*.*.............*.*.. ..*...*...........*...*.. ..*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................*.. ..*.*.............................*.*.. ..*...*...........................*...*.. ..*.*.*.*.........................*.*.*.*.. ..*.......*.......................*.......*.. ..*.*.....*.*.....................*.*.....*.*.. ..*...*...*...*...................*...*...*...*.. ..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. ..*...............*...............*...............*.. ..*.*.............*.*.............*.*.............*.*.. ..*...*...........*...*...........*...*...........*...*.. ..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.......*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................................................*.. ..*.*.............................................................*.*.. ..*...*...........................................................*...*..
Mathematica / Wolfram Language
An infinite background is built-in the language:
CellularAutomaton[18, {{1}, 0}, 15] // ArrayPlot
CellularAutomaton[30, {{1}, 0}, 15] // ArrayPlot
Nim
import strutils
func step(cells: string; rule: int): string =
for i in 0..(cells.len - 3):
var bin = 0
var b = 2
for n in i..(i + 2):
inc bin, ord(cells[n] == '*') shl b
b = b shr 1
let a = if (rule and 1 shl bin) != 0: '*' else: '.'
result.add(a)
func addNoCells(cells: var string) =
let left = if cells[0] == '*': "." else: "*"
let right = if cells[^1] == '*': "." else: "*"
cells.insert(left)
cells.add(right)
cells.insert(left)
cells.add(right)
proc evolve(limit, rule: int) =
echo "Rule #", rule
var cells = "*"
for _ in 0..<limit:
cells.addNoCells()
let width = 40 + cells.len shr 1
echo cells.align(width)
cells = cells.step(rule)
evolve(35, 90)
- Output:
Rule #90 ..*.. ..*.*.. ..*...*.. ..*.*.*.*.. ..*.......*.. ..*.*.....*.*.. ..*...*...*...*.. ..*.*.*.*.*.*.*.*.. ..*...............*.. ..*.*.............*.*.. ..*...*...........*...*.. ..*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................*.. ..*.*.............................*.*.. ..*...*...........................*...*.. ..*.*.*.*.........................*.*.*.*.. ..*.......*.......................*.......*.. ..*.*.....*.*.....................*.*.....*.*.. ..*...*...*...*...................*...*...*...*.. ..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. ..*...............*...............*...............*.. ..*.*.............*.*.............*.*.............*.*.. ..*...*...........*...*...........*...*...........*...*.. ..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.......*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................................................*.. ..*.*.............................................................*.*.. ..*...*...........................................................*...*..
Perl
The edges of a pattern is implicitly repeating. The code will try to lineup output by padding up to 40 spaces to the left, but since the cells keep expanding, that has to end somewhere.
sub evolve {
my ($rule, $pattern) = @_;
my $offset = 0;
while (1) {
my ($l, $r, $st);
$pattern =~ s/^((.)\g2*)/$2$2/ and $l = $2, $offset -= length($2);
$pattern =~ s/(.)\g1*$/$1$1/ and $r = $1;
$st = $pattern;
$pattern =~ tr/01/.#/;
printf "%5d| %s%s\n", $offset, ' ' x (40 + $offset), $pattern;
$pattern = join '', map(1 & ($rule>>oct "0b$_"),
$l x 3,
map(substr($st, $_, 3), 0 .. length($st)-3),
$r x 3);
}
}
evolve(90, "010");
- Output:
-1| ..#.. -2| ..#.#.. -3| ..#...#.. -4| ..#.#.#.#.. -5| ..#.......#.. -6| ..#.#.....#.#.. -7| ..#...#...#...#.. -8| ..#.#.#.#.#.#.#.#.. -9| ..#...............#.. -10| ..#.#.............#.#.. -11| ..#...#...........#...#.. -12| ..#.#.#.#.........#.#.#.#.. -13| ..#.......#.......#.......#.. ---(infinite more lines snipped)---
Phix
Uses 0-expansion either side
with javascript_semantics string s = ".#.", t=s, r = "........" integer rule = 18, k, l = length(s), w = 0 for i=1 to 8 do r[i] = iff(mod(rule,2)?'#':'.') rule = floor(rule/2) end for for i=0 to 25 do ?repeat(' ',floor((55-length(s))/2))&s for j=1 to l do k = (s[iff(j=1?l:j-1)]='#')*4 + (s[ j ]='#')*2 + (s[iff(j=l?1:j+1)]='#')+1 t[j] = r[k] end for if t[1]='#' then t = '.'&t end if if t[$]='#' then t = t&'.' end if l = length(t) s = t end for
- Output:
" .#." " .#.#." " .#...#." " .#.#.#.#." " .#.......#." " .#.#.....#.#." " .#...#...#...#." " .#.#.#.#.#.#.#.#." " .#...............#." " .#.#.............#.#." " .#...#...........#...#." " .#.#.#.#.........#.#.#.#." " .#.......#.......#.......#." " .#.#.....#.#.....#.#.....#.#." " .#...#...#...#...#...#...#...#." " .#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#." " .#...............................#." " .#.#.............................#.#." " .#...#...........................#...#." " .#.#.#.#.........................#.#.#.#." " .#.......#.......................#.......#." " .#.#.....#.#.....................#.#.....#.#." " .#...#...#...#...................#...#...#...#." " .#.#.#.#.#.#.#.#.................#.#.#.#.#.#.#.#." " .#...............#...............#...............#." " .#.#.............#.#.............#.#.............#.#."
Python
Infinite generator but only print 25 lines of each rule.
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 = 25
for rule in (90, 30):
print('\nRule: %i' % rule)
for i, c in zip(range(lines), eca_infinite('1', rule)):
print('%2i: %s%s' % (i, ' '*(lines - i), c.replace('0', '.').replace('1', '#')))
- Output:
Rule: 90 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: #...............#...............#...............# Rule: 30 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: ##..#...###..####...##.#####...#.#####.#..#.....#
Racket
Uses solution to Elementary cellular automaton saved in file "Elementary_cellular_automata.rkt"
#lang racket
; below is the code from the parent task
(require "Elementary_cellular_automata.rkt")
(require racket/fixnum)
(define (wrap-rule-infinite v-in vl-1 offset)
(define l-bit-set? (bitwise-bit-set? (fxvector-ref v-in 0) usable-bits/fixnum-1))
(define r-bit-set? (bitwise-bit-set? (fxvector-ref v-in vl-1) 0))
;; if we need to extend left offset is reduced by 1
(define l-pad-words (if l-bit-set? 1 0))
(define r-pad-words (if r-bit-set? 1 0))
(define new-words (fx+ l-pad-words r-pad-words))
(cond
[(fx= 0 new-words) (values v-in vl-1 offset)] ; nothing changes
[else
(define offset- (if l-bit-set? (fx- offset 1) offset))
(define l-sequence (if l-bit-set? (in-value 0) (in-sequences)))
(define vl-1+ (fx+ vl-1 (fx+ l-pad-words r-pad-words)))
(define v-out
(for/fxvector
#:length (fx+ vl-1+ 1) #:fill 0 ; right padding
([f (in-sequences l-sequence (in-fxvector v-in))])
f))
(values v-out vl-1+ offset-)]))
(module+ main
(define ng/90/infinite (CA-next-generation 90 #:wrap-rule wrap-rule-infinite))
(for/fold ([v (fxvector #b10000000000000000000)]
[o 1]) ; start by pushing output right by one
([step (in-range 40)])
(show-automaton v #:step step #:push-right o)
(newline)
(ng/90/infinite v o)))
- Output:
[ 0] ..............................000000000010000000000000000000 [ 1] ..............................000000000101000000000000000000 [ 2] ..............................000000001000100000000000000000 [ 3] ..............................000000010101010000000000000000 [ 4] ..............................000000100000001000000000000000 [ 5] ..............................000001010000010100000000000000 [ 6] ..............................000010001000100010000000000000 [ 7] ..............................000101010101010101000000000000 [ 8] ..............................001000000000000000100000000000 [ 9] ..............................010100000000000001010000000000 [ 10] ..............................100010000000000010001000000000 [ 11] 000000000000000000000000000001010101000000000101010100000000 [ 12] 000000000000000000000000000010000000100000001000000010000000 [ 13] 000000000000000000000000000101000001010000010100000101000000 [ 14] 000000000000000000000000001000100010001000100010001000100000 [ 15] 000000000000000000000000010101010101010101010101010101010000 [ 16] 000000000000000000000000100000000000000000000000000000001000 [ 17] 000000000000000000000001010000000000000000000000000000010100 [ 18] 000000000000000000000010001000000000000000000000000000100010 [ 19] 000000000000000000000101010100000000000000000000000001010101 [ 20] 000000000000000000001000000010000000000000000000000010000000100000000000000000000000000000 [ 21] 000000000000000000010100000101000000000000000000000101000001010000000000000000000000000000 [ 22] 000000000000000000100010001000100000000000000000001000100010001000000000000000000000000000 [ 23] 000000000000000001010101010101010000000000000000010101010101010100000000000000000000000000 [ 24] 000000000000000010000000000000001000000000000000100000000000000010000000000000000000000000 [ 25] 000000000000000101000000000000010100000000000001010000000000000101000000000000000000000000 [ 26] 000000000000001000100000000000100010000000000010001000000000001000100000000000000000000000 [ 27] 000000000000010101010000000001010101000000000101010100000000010101010000000000000000000000 [ 28] 000000000000100000001000000010000000100000001000000010000000100000001000000000000000000000 [ 29] 000000000001010000010100000101000001010000010100000101000001010000010100000000000000000000 [ 30] 000000000010001000100010001000100010001000100010001000100010001000100010000000000000000000 [ 31] 000000000101010101010101010101010101010101010101010101010101010101010101000000000000000000 [ 32] 000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000 [ 33] 000000010100000000000000000000000000000000000000000000000000000000000001010000000000000000 [ 34] 000000100010000000000000000000000000000000000000000000000000000000000010001000000000000000 [ 35] 000001010101000000000000000000000000000000000000000000000000000000000101010100000000000000 [ 36] 000010000000100000000000000000000000000000000000000000000000000000001000000010000000000000 [ 37] 000101000001010000000000000000000000000000000000000000000000000000010100000101000000000000 [ 38] 001000100010001000000000000000000000000000000000000000000000000000100010001000100000000000 [ 39] 010101010101010100000000000000000000000000000000000000000000000001010101010101010000000000 #fx(536879104 0 33554944) 0
Raku
(formerly Perl 6) This version, while it is capable of working with infinite length cellular automata, makes the assumption that any cells which have not been explicitly examined are in a 'null' state, neither '0' or '1'. Further it makes the assumption that a null cell, on being examined, initially contains nothing (░). Otherwise it would take infinite time to calculate every row and would be exceptionally boring to watch.
Based heavily on the code from the One-dimensional cellular automata task. Example uses rule 90 (Sierpinski triangle).
class Automaton {
has $.rule;
has @.cells;
has @.code = $!rule.fmt('%08b').flip.comb».Int;
method gist { @!cells.map({+$_ ?? '▲' !! '░'}).join }
method succ {
self.new: :$!rule, :@!code, :cells(
' ',
|@!code[
4 «*« @!cells.rotate(-1)
»+« 2 «*« @!cells
»+« @!cells.rotate(1)
],
' '
)
}
}
my Automaton $a .= new: :rule(90), :cells(flat '010'.comb);
# display the first 20 rows
say $a++ for ^20;
# then calculate the other infinite number of rows, (may take a while)
$a++ for ^Inf;
- Output:
░▲░ ░▲░▲░ ░▲░░░▲░ ░▲░▲░▲░▲░ ░▲░░░░░░░▲░ ░▲░▲░░░░░▲░▲░ ░▲░░░▲░░░▲░░░▲░ ░▲░▲░▲░▲░▲░▲░▲░▲░ ░▲░░░░░░░░░░░░░░░▲░ ░▲░▲░░░░░░░░░░░░░▲░▲░ ░▲░░░▲░░░░░░░░░░░▲░░░▲░ ░▲░▲░▲░▲░░░░░░░░░▲░▲░▲░▲░ ░▲░░░░░░░▲░░░░░░░▲░░░░░░░▲░ ░▲░▲░░░░░▲░▲░░░░░▲░▲░░░░░▲░▲░ ░▲░░░▲░░░▲░░░▲░░░▲░░░▲░░░▲░░░▲░ ░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░▲░ ░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░ ░▲░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░▲░ ░▲░░░▲░░░░░░░░░░░░░░░░░░░░░░░░░░░▲░░░▲░ ░▲░▲░▲░▲░░░░░░░░░░░░░░░░░░░░░░░░░▲░▲░▲░▲░ ^C
Ruby
def notcell(c)
c.tr('01','10')
end
def eca_infinite(cells, rule)
neighbours2next = Hash[8.times.map{|i|["%03b"%i, "01"[rule[i]]]}]
c = cells
Enumerator.new do |y|
loop do
y << c
c = notcell(c[0])*2 + c + notcell(c[-1])*2 # Extend and pad the ends
c = (1..c.size-2).map{|i| neighbours2next[c[i-1..i+1]]}.join
end
end
end
if __FILE__ == $0
lines = 25
for rule in [90, 30]
puts "\nRule: %i" % rule
for i, c in (0...lines).zip(eca_infinite('1', rule))
puts '%2i: %s%s' % [i, ' '*(lines - i), c.tr('01', '.#')]
end
end
end
The output is the same as the Python entry.
Sidef
func evolve(rule, bin) {
var offset = 0
var (l='', r='')
Inf.times {
bin.sub!(/^((.)\g2*)/, {|_s1, s2| l = s2; offset -= s2.len; s2*2 })
bin.sub!(/(.)\g1*$/, {|s1| r = s1; s1*2 })
printf("%5d| %s%s\n", offset, ' ' * (40 + offset), bin.tr('01','.#'))
bin = [l*3, 0.to(bin.len-3).map{|i| bin.substr(i, 3) }..., r*3 ].map { |t|
1 & (rule >> t.bin)
}.join
}
}
evolve(90, "010")
- Output:
-1| ..#.. -2| ..#.#.. -3| ..#...#.. -4| ..#.#.#.#.. -5| ..#.......#.. -6| ..#.#.....#.#.. -7| ..#...#...#...#.. -8| ..#.#.#.#.#.#.#.#.. -9| ..#...............#.. -10| ..#.#.............#.#.. -11| ..#...#...........#...#.. -12| ..#.#.#.#.........#.#.#.#.. -13| ..#.......#.......#.......#.. -14| ..#.#.....#.#.....#.#.....#.#.. -15| ..#...#...#...#...#...#...#...#.. -16| ..#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.. -17| ..#...............................#.. -18| ..#.#.............................#.#.. -19| ..#...#...........................#...#.. -20| ..#.#.#.#.........................#.#.#.#.. ⋮
Tcl
package require Tcl 8.6
oo::class create InfiniteElementaryAutomaton {
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 {left state right} {
set state [list $left {*}$state $right]
set len [llength $state]
for {set i -1;set j 0;set k 1} {$j < $len} {incr i;incr j;incr k} {
set a [expr {$i<0 ? $left : [lindex $state $i]}]
set b [lindex $state $j]
set c [expr {$k==$len ? $right : [lindex $state $k]}]
lappend result [dict get $rules $a$b$c]
}
return $result
}
method evolveEnd {endState} {
return [dict get $rules $endState$endState$endState]
}
# Simple driver method; omit the initial state to get a centred dot
method run {steps {initialState "010"}} {
set cap [string repeat "\u2026" $steps]
set s [split [string map ". 0 # 1" $initialState] ""]
set left [lindex $s 0]
set right [lindex $s end]
set s [lrange $s 1 end-1]
for {set i 0} {$i < $steps} {incr i} {
puts $cap[string map "0 . 1 #" $left[join $s ""]$right]$cap
set s [my evolve $left $s $right]
set left [my evolveEnd $left]
set right [my evolveEnd $right]
set cap [string range $cap 1 end]
}
puts $cap[string map "0 . 1 #" $left[join $s ""]$right]$cap
}
}
foreach num {90 30} {
puts "Rule ${num}:"
set rule [InfiniteElementaryAutomaton new $num]
$rule run 25
$rule destroy
}
- Output:
Rule 90: ………………………………………………………………….#.………………………………………………………………… ……………………………………………………………….#.#.……………………………………………………………… …………………………………………………………….#...#.…………………………………………………………… ………………………………………………………….#.#.#.#.………………………………………………………… ……………………………………………………….#.......#.……………………………………………………… …………………………………………………….#.#.....#.#.…………………………………………………… ………………………………………………….#...#...#...#.………………………………………………… ……………………………………………….#.#.#.#.#.#.#.#.……………………………………………… …………………………………………….#...............#.…………………………………………… ………………………………………….#.#.............#.#.………………………………………… ……………………………………….#...#...........#...#.……………………………………… …………………………………….#.#.#.#.........#.#.#.#.…………………………………… ………………………………….#.......#.......#.......#.………………………………… ……………………………….#.#.....#.#.....#.#.....#.#.……………………………… …………………………….#...#...#...#...#...#...#...#.…………………………… ………………………….#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.………………………… ……………………….#...............................#.……………………… …………………….#.#.............................#.#.…………………… ………………….#...#...........................#...#.………………… ……………….#.#.#.#.........................#.#.#.#.……………… …………….#.......#.......................#.......#.…………… ………….#.#.....#.#.....................#.#.....#.#.………… ……….#...#...#...#...................#...#...#...#.……… …….#.#.#.#.#.#.#.#.................#.#.#.#.#.#.#.#.…… ….#...............#...............#...............#.… .#.#.............#.#.............#.#.............#.#. Rule 30: ………………………………………………………………….#.………………………………………………………………… ……………………………………………………………….###.……………………………………………………………… …………………………………………………………….##..#.…………………………………………………………… ………………………………………………………….##.####.………………………………………………………… ……………………………………………………….##..#...#.……………………………………………………… …………………………………………………….##.####.###.…………………………………………………… ………………………………………………….##..#....#..#.………………………………………………… ……………………………………………….##.####..######.……………………………………………… …………………………………………….##..#...###.....#.…………………………………………… ………………………………………….##.####.##..#...###.………………………………………… ……………………………………….##..#....#.####.##..#.……………………………………… …………………………………….##.####..##.#....#.####.…………………………………… ………………………………….##..#...###..##..##.#...#.………………………………… ……………………………….##.####.##..###.###..##.###.……………………………… …………………………….##..#....#.###...#..###..#..#.…………………………… ………………………….##.####..##.#..#.#####..#######.………………………… ……………………….##..#...###..####.#....###......#.……………………… …………………….##.####.##..###....##..##..#....###.…………………… ………………….##..#....#.###..#..##.###.####..##..#.………………… ……………….##.####..##.#..######..#...#...###.####.……………… …………….##..#...###..####.....####.###.##...#...#.…………… ………….##.####.##..###...#...##....#...#.#.###.###.………… ……….##..#....#.###..#.###.##.#..###.##.#.#...#..#.……… …….##.####..##.#..###.#...#..####...#..#.##.######.…… ….##..#...###..####...##.#####...#.#####.#..#.....#.… .##.####.##..###...#.##..#....#.##.#.....#####...###.
Wren
import "./fmt" for Fmt
var addNoCells = Fn.new { |s|
var l = (s[0] == "*") ? "." : "*"
var r = (s[-1] == "*") ? "." : "*"
for (i in 0..1) {
s.insert(0, l)
s.add(r)
}
}
var step = Fn.new { |cells, rule|
var newCells = []
for (i in 0...cells.count - 2) {
var bin = 0
var b = 2
for (n in i...i + 3) {
bin = bin + (((cells[n] == "*") ? 1 : 0) << b)
b = b >> 1
}
var a = ((rule & (1 << bin)) != 0) ? "*" : "."
newCells.add(a)
}
return newCells
}
var evolve = Fn.new { |l, rule|
System.print(" Rule #%(rule):")
var cells = ["*"]
for (x in 0...l) {
addNoCells.call(cells)
var width = 40 + (cells.count >> 1)
Fmt.print("$*s", width, cells.join())
cells = step.call(cells, rule)
}
}
evolve.call(35, 90)
System.print()
- Output:
Rule #90: ..*.. ..*.*.. ..*...*.. ..*.*.*.*.. ..*.......*.. ..*.*.....*.*.. ..*...*...*...*.. ..*.*.*.*.*.*.*.*.. ..*...............*.. ..*.*.............*.*.. ..*...*...........*...*.. ..*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................*.. ..*.*.............................*.*.. ..*...*...........................*...*.. ..*.*.*.*.........................*.*.*.*.. ..*.......*.......................*.......*.. ..*.*.....*.*.....................*.*.....*.*.. ..*...*...*...*...................*...*...*...*.. ..*.*.*.*.*.*.*.*.................*.*.*.*.*.*.*.*.. ..*...............*...............*...............*.. ..*.*.............*.*.............*.*.............*.*.. ..*...*...........*...*...........*...*...........*...*.. ..*.*.*.*.........*.*.*.*.........*.*.*.*.........*.*.*.*.. ..*.......*.......*.......*.......*.......*.......*.......*.. ..*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.....*.*.. ..*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*.. ..*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.. ..*...............................................................*.. ..*.*.............................................................*.*.. ..*...*...........................................................*...*..
zkl
nLines,flipCell := 25, fcn(c){ (c=="1") and "0" or "1" };
foreach rule in (T(90,30)){
println("\nRule: ", rule);
ruleBits:="%08.2B".fmt(rule); // eg 90-->"01011010"
neighs2next:=(8).pump(Dictionary(),
'wrap(n){ T("%03.2B".fmt(n), ruleBits.reverse()[n]) });
C:="1"; // C is "1"s and "0"s, I'll auto cast to Int as needed
foreach i in (nLines){
println("%2d: %s%s".fmt(i," "*(nLines - i), C.translate("01",".#")));
C=String(flipCell(C[0])*2, C, flipCell(C[-1])*2);
C=[1..C.len()-2].pump(String,'wrap(n){ neighs2next[C[n-1,3]] });
}
}
- Output:
Rule: 90 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: #...............#...............#...............# Rule: 30 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: ##..#...###..####...##.#####...#.#####.#..#.....#