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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
--
--------------------------------------------------------------------------------
-- FILE: automata-eca.lua
-- DESCRIPTION: drawing elementary cellular automata
-- REQUIREMENTS: ConTeXt MkIV with Simple Slides module
-- BUGS: uncountable minus the few I found
-- AUTHOR: Philipp Gesang (Phg), <megas.kapaneus@gmail.com>
-- VERSION: 1.0
-- CREATED: 14/08/10 19:43:35 CEST
--------------------------------------------------------------------------------
--
if context then
environment.loadluafile( "automata-life" )
else
require "automata-life"
end
local help = gol.helpers
local C, Cs, Ct, P, R, S, match = lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.match
eca = {}
function eca.parse_file (fname)
local f = assert(io.open(fname, "r"), "No such file: "..fname..".")
local init = f:read("*all")
f:close()
return help.strip(init)
end
function eca.to_base(number, base)
local alphabet, result, cnt, remainder = "0123456789abcdef", "", 0
while number > 0 do
cnt = cnt + 1
number, remainder = math.floor(number / base), (number % base) + 1
result = string.sub(alphabet, remainder, remainder) .. result
end
return result
end
function eca.gen_rule(nr)
local rules = {}
local states = { "111", "110", "101", "100", "011", "010", "001", "000" }
nr = string.format("%8s",eca.to_base(nr, 2)):gsub(" ", "0")
local n = 1
while n <= #states do
rules[states[n]] = nr:sub(n,n)
n = n + 1
end
return rules
end
function eca.next_line(from, rule)
local new = ""
from = "0"..from.."0" -- assume dead borders
--from = string.format("0%s0", from) -- too slow
local cell = C(S"01")
--local cells= Ct(cell * #(cell * cell)) / function (t) -- I ♡ LPEG
-- local three = t[1]..t[2]..t[3]
-- new = new .. rule[three]
--end
--lpeg.match(cells^1, from)
for i=1, #from - 2 do
local three = from:sub(i, i+2)
new = new .. rule[three]
end
return new
end
function eca.stripcells (str, dir, cnt)
if dir == "left" then
return str:sub( cnt )
elseif dir == "right" then
return str:sub( 0, str:len() - cnt )
else -- assume ambilateral clipping
return str:sub( cnt, str:len() - cnt )
end
end
function eca.gen_frame(from, lines, rule)
local cnt = 1
local c = mplife.setup.current
local new = { [1] = eca.stripcells(from, c.clip, c.diff or 0 ) }
repeat
from = eca.next_line(from, rule)
table.insert( new, eca.stripcells(from, c.clip, c.diff or 0) )
cnt = cnt + 1
until cnt == lines
return eca.next_line(from, rule), new
end
function eca.successive (current)
local thisframe
current.from, thisframe = eca.gen_frame(current.from, current.framesize, current.rule)
for _,j in ipairs(thisframe) do
io.write(j:gsub("0","·"):gsub("1","O").."\n")
end
return 0
end
return eca
|