-
Notifications
You must be signed in to change notification settings - Fork 0
/
automata.rb
66 lines (55 loc) · 1.82 KB
/
automata.rb
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
# CellularAutomaton
# https://en.wikipedia.org/wiki/Cellular_automaton
# https://en.wikipedia.org/wiki/Elementary_cellular_automaton
# http://mathworld.wolfram.com/CellularAutomaton.html
# http://mathworld.wolfram.com/ElementaryCellularAutomaton.html
module Automata
class ElementaryCA
attr_accessor :rule, :transition, :state, :width
DEFAULT_OPTS = {
rule: 30, # from 0 to 255
width: 32,
start: :middle # :left, :middle, :right
}
def initialize(opts = {})
opts = DEFAULT_OPTS.merge(opts)
@rule = opts[:rule]
@width = opts[:width]
set_transition_table(opts[:rule])
set_initital_state(opts[:start])
end
def set_transition_table(rule)
binary = '%08d' % rule.to_s(2)
combinations = (0..7).map { |n| '%03d' % n.to_s(2) }
@transition = combinations.map do |n|
[n, binary.slice!(-1)]
end.to_h
end
def set_initital_state(start)
@state = '0'* @width
@state[0] = '1' if start == :left
@state[@width/2] = '1' if start == :middle
@state[@width-1] = '1' if start == :right
end
def evolve
new_state = '0'* @width
(0..@width-1).each do |i|
pattern = @state[i-1,3]
if i == 0
pattern = @state[-1]+@state[0,2]
elsif i == (@width-1)
pattern = @state[i-1,2]+@state[0]
end
new_state[i] = transition[pattern]
end
@state = new_state
end
end
end
# usage
# $ irb
# require './algorithms/automata.rb'
# automaton = Automata::ElementaryCA.new(rule: 30, width: 32, start: :middle)
# 16.times do puts automaton.state; automaton.evolve end
# automaton = Automata::ElementaryCA.new(rule: 110, width: 32, start: :right)
# 32.times do puts automaton.state; automaton.evolve end