プログラムのランダム生成作ってみました
マルコフ連鎖を利用してプログラムをランダムに作るプログラムを作ってみました。種のプログラムを指定するとそれを元に、推移表を作ってプログラムを合成します。SEEDPROG定数に種になるプログラムのファイル名を指定します。pcompose.rbはこの生成プログラムの名前です。
PREVSTATを変えると、推移表が過去どれだけのトークンを見るかを変えられます。
ripperを使っているので、1.9以降じゃないと動かないです。
# プログラムランダム合成のテスト require 'pp' require 'ripper' SEEDPROG = "pcompose.rb" PREVSTAT = [nil, nil, nil] class MaTable def initialize @cont = {} end def []=(keys, value) cc = @cont lkey = keys.last keys[0..-2].each do |k| cc[k] ||= {} cc = cc[k] end cc[lkey] ||= [] cc[lkey].push value if !cc[lkey].include?(value) end def [](keys) cc = @cont keys[0..-2].each do |k| if cc[k] then cc = cc[k] end end cc[keys.last] end end mtable = MaTable.new tokens = Ripper.tokenize(File.read(SEEDPROG)) prevtok = PREVSTAT.dup tokens.each do |tok| mtable[prevtok] = tok prevtok.push(tok) prevtok.shift end otok = PREVSTAT.dup endlevel = nil while endlevel != 0 do toks = mtable[otok] ch = rand(toks.size) ctok = toks[ch] # endlevelを動かす特殊なトークンをチェック case ctok when 'class' when 'module' when 'begin' when 'while' when 'case' when 'if' when 'do' when 'def' when '{' endlevel ||= 0 endlevel += 1 when '}' when 'end' if endlevel != nil then endlevel -= 1 end end otok.push ctok otok.shift print ctok end
実行例です。括弧の対応とかもうちょっと工夫が必要ですが、なかなか面白そうです。
その1
# プログラムランダム合成のテスト require 'ripper' SEEDPROG = @cont lkey = rand(toks.size) ctok = @cont keys[0..-2].each do |tok| mtable[otok] ch = cc[k] end cc = {} end
その2
# プログラムランダム合成のテスト require 'pp' require 'ripper' SEEDPROG = "pcompose.rb" PREVSTAT = rand(toks.size) prevtok.shift print ctok when '{' if endlevel != 0 do toks = mtable[prevtok] = keys.last keys[0..-2].each do |tok| mtable[otok] ch = toks[ch] class MaTable def initialize @cont = Ripper.tokenize(File.read(SEEDPROG)) prevtok = rand(toks.size) ctok = @cont keys[0..-2].each do |tok| mtable[prevtok] = "pcompose.rb" PREVSTAT = tok prevtok.push(tok) prevtok.push(tok) end