セルオートマトンとは
wikiが充実してるのでそちらを。
単純なコードで目に楽しい出力です。
ちなみに二次元セルオートマトンはライフゲームという名で有名ですね。
Rubyで
やってみます。
make_all_pattern
一次元の場合パターンが256しかないので、力任せに全てのパターンを生成します。
8重forという酷いコード。
class Cells
attr :table, :cells
def initialize
@cells = [1]
@table = make_all_patterns
end
def make_all_patterns
cs = [0,1]
ops = []
ips = []
ps = []
for i1 in cs
for i2 in cs
for i3 in cs
ips.push [i1,i2,i3]
end
end
end
for o1 in cs
for o2 in cs
for o3 in cs
for o4 in cs
for o5 in cs
for o6 in cs
for o7 in cs
for o8 in cs
os = [o1,o2,o3,o4,o5,o6,o7,o8]
n = os.map { |o| o.to_s }.reduce(:+).to_i(2)
ops[n] = os
end
end
end
end
end
end
end
end
ops.each_with_index { |os,n|
ps[n] = {}
for o,i in os.reverse.zip ips
ps[n][i] = o
end
}
ps
end
apply
各セルにパターンを適応します。
両端に一つずつセルを追加して成長させ、
周囲のセルの状態と自分の状態で次の状態をパターンによって決めていきます。
パターンマッチはただのHashでできてしまいました。Rubyすごい。
def apply pn
pt = @table[pn]
s = @cells.size
f = -> i { (i < 0 || i >= s) ? 0 : @cells[i] }
newCells = []
for i in -1 .. s
cs = [f.call(i-1), f.call(i), f.call(i+1)]
newCells.push(pt[cs])
end
@cells = newCells
end
show
パターンとセルを見やすく。
def show_cells
#@cells.map { |c| c == 1 ? "O" : " " }.join
@cells.join
end
def show_table pn
"[#{pn}] " +
@table[pn].keys.map { |k| "#{k.join} = #{@table[pn][k]}" }.join(", ")
end
run
ビジュアライズ。
runの引数は0から255までで。
ターミナルの幅と高さに合わせて表示。
表示が終わったところで@cellsを初期化しておきます。
require "io/console"
def run pn
raise "expected arg in 0..255" unless pn < 256
puts show_table pn
rs, cs = IO.console.winsize
(rs - 2).times {
puts show_cells.center(cs)
apply pn
}
@cells = [1]
end
end
main
折角なので全パターン実行。
newで全パターン生成してるのでuptoの外に。
sleepで目で追える程度に調整。
cs = Cells.new
0.upto(255) { |n|
cs.run(n)
sleep 0.3
}
ルール90
こんな感じで表示されます。
[90] 000 = 0, 001 = 1, 010 = 0, 011 = 1, 100 = 1, 101 = 0, 110 = 1, 111 = 0
1 101 10001 1010101 100000001 10100000101 1000100010001 101010101010101 10000000000000001 1010000000000000101 100010000000000010001 10101010000000001010101 1000000010000000100000001 101000001010000010100000101 10001000100010001000100010001 1010101010101010101010101010101 100000000000000000000000000000001 10100000000000000000000000000000101 1000100000000000000000000000000010001 101010100000000000000000000000001010101 10000000100000000000000000000000100000001 1010000010100000000000000000000010100000101 100010001000100000000000000000001000100010001 10101010101010100000000000000000101010101010101 1000000000000000100000000000000010000000000000001 101000000000000010100000000000001010000000000000101 10001000000000001000100000000000100010000000000010001 1010101000000000101010100000000010101010000000001010101 100000001000000010000000100000001000000010000000100000001 10100000101000001010000010100000101000001010000010100000101 1000100010001000100010001000100010001000100010001000100010001 101010101010101010101010101010101010101010101010101010101010101
終
make_all_patternsの8重forがダサいですが、
パターンマッチがHashで済んでしまう所はクールでした。
簡単ながらそこそこ作り甲斐があるので新しい言語覚える時は、
hello,worldの代わりに書いたりしてます。