METHINKS IT IS A WEASEL
Posted feedbacks - Ruby
ちょっと遅いですが...。
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 | #! /usr/bin/ruby
class Text
GOAL = 'METHINKSITISAWEASEL'
CHARACTER_SET = ('A'..'Z').to_a
attr_accessor :text
def create
self.text = (1..GOAL.length).map { |_| CHARACTER_SET[rand(CHARACTER_SET.length)] }.to_s
self
end
def update
self.text[rand(GOAL.length)] = CHARACTER_SET[rand(CHARACTER_SET.length)]
self
end
def rank
self.text.split('').zip(GOAL.split('')).inject(0) { |r,s| s[0] == s[1] ? r + 1 : r }
end
def complete?
self.rank == GOAL.length
end
def clone
copy = super
copy.text = self.text.clone
copy
end
end
class Processor
POOL_SIZE = 300
COPY_SIZE = 3
attr_accessor :text_list
def initialize
self.text_list = (1..POOL_SIZE).map { |_| Text.new.create }.sort { |a,b| b.rank <=> a.rank }
self
end
def process
self.text_list = self.text_list.map { |t| (1..COPY_SIZE).map { |_| t.clone.update } }.flatten.sort { |a,b| b.rank <=> a.rank }.first(POOL_SIZE)
self
end
def complete?
self.text_list.first.complete?
end
end
i = 1
processor = Processor.new
until processor.complete? do
puts "process(#{i}): #{processor.text_list.first.text}(#{processor.text_list.first.rank})"
processor.process
i = i + 1
end
puts "complete(#{i}): #{processor.text_list.first.text}"
|
素朴に書いてみました。
Ruby-1.8.x系だと滅茶苦茶遅いですが、Ruby-1.9.1だと阿呆みたいに速くなりますね……。
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 | TARGET = "METHINKSITISAWEASEL".split("")
class Array
def choice
self[rand(self.size)]
end
end
def rand_char
('A'..'Z').to_a.choice
end
def gen
(1..300).map{ (1..TARGET.size).inject(""){|r,s|r+=rand_char()} }
end
def weasel_sort(arr)
arr.sort_by{|s| rank = 0;s.each_char.with_index{|c, i|;rank += 1 if c != TARGET[i]};rank}
end
def evolve(arr)
arr.map{|word| (1..10).map{ t=word.dup;i = rand(word.size);t[i]=rand_char;t}}.flatten
end
def generate_passage
rc = gen
i = -1
until rc[0].split("") == TARGET
i += 1
rc = evolve rc
rc = weasel_sort rc
rc = rc[0..299]
puts "generation #{i}: ", "\t" + rc[0..5].join(" ")
end
return i
end
if $0 == __FILE__
TARGET = ARGV.fetch(0, "METHINKSITISAWEASEL").upcase.split("")
generate_passage()
end
|


ytakenaka
#6287()
Rating4/8=0.50
ランダムな文字からMETHINKS IT IS A WEASELを作るプログラムを作れ。
簡単に流れを書いてみます。
1:ランダムな20文字を持つ文字列をもった300個作ります。
2:その文字列が"METHINKSITISAWEASEL"に近いものからソートします。
3:それぞれの文字列のなか1文字を別の文字に変化させたものを3つ用意します。
4:それを2:のソートをして上位300個残す。(900個あるうちで上位300個残すということです。)
5:以後3:と4:を繰り返す。
ランダムな文字変化は大文字だけでいいです。簡単にするために空白文字を外してあります。
METHINKS IT IS WEASELができたら終了。3と4の間でソートしたもので一番上位のものを毎回表示させると変化が楽しめます。:-)
Rickard Dawkinsがブラインドウォッチメイカー(現題:盲目の時計職人)の3章で書いていた有名なものです。さらに一般化してもらってもいいです。
参考
[ reply ]