-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathelementary_cellular_automaton_generalized.pl
executable file
·73 lines (51 loc) · 1.94 KB
/
elementary_cellular_automaton_generalized.pl
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# Date: 16 October 2019
# https://github.com/trizen
# Generalization of the elementary cellular automaton, by using `n` color-states and looking at `k` neighbors left-to-right.
# For example, a value of `n = 3` and `k = 2` uses three different color-states and looks at 2 neighbors to the left and 2 neighbors to the right.
# See also:
# https://en.wikipedia.org/wiki/Cellular_automaton
# https://en.wikipedia.org/wiki/Elementary_cellular_automaton
# https://rosettacode.org/wiki/Elementary_cellular_automaton
# YouTube lectures:
# https://www.youtube.com/watch?v=S3tYzCPuVsA
# https://www.youtube.com/watch?v=pGGIE5uhPRQ
use 5.020;
use strict;
use warnings;
use ntheory qw(:all);
use experimental qw(signatures);
use Algorithm::Combinatorics qw(variations_with_repetition);
sub automaton ($n, $k, $rule, $callback, $iter = 50, $cells = [1]) {
my @states = variations_with_repetition([0 .. $n - 1], 2 * $k + 1);
my @digits = reverse todigits($rule, $n);
my @lookup;
foreach my $i (0 .. $#states) {
$lookup[fromdigits($states[$i], $n)] = $digits[$i] // 0;
}
my @padding = (0) x (($iter - scalar(@$cells)) >> 1);
my @cells = (@padding, @$cells, @padding);
my @neighbors_range = (-$k .. $k);
my $len = scalar(@cells);
for (1 .. ($iter >> 1)) {
$callback->(@cells);
@cells = @lookup[map {
my $i = $_; fromdigits([map { $cells[($i + $_) % $len] } @neighbors_range], $n)
} 0 .. $#cells];
}
return @cells;
}
my @chars = (' ', '*', '.', '#');
say "\n=> 2x1 Automaton";
automaton(2, 1, 90, sub (@row) {
say join '', map { $chars[$_] } @row;
});
say "\n=> 3x1 Automaton";
automaton(3, 1, "843693805713", sub (@row) {
say join '', map { $chars[$_] } @row;
});
say "\n=> 3x2 Automaton";
automaton(3, 2, "590193390821886729275563552433397050190", sub (@row) {
say join '', map { $chars[$_] } @row;
}, 80);