どう書く?org : METHINKS IT IS A WEASEL

original page : http://ja.doukaku.org/177/

ランダムな文字から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章で書いていた有名なものです。さらに一般化してもらってもいいです。

参考

* http://home.pacbell.net/s-max/scott/weasel.html (JAVA アプレット)

* http://en.wikipedia.org/wiki/Weasel_program

#6801

original page : http://ja.doukaku.org/comment/6801/

Rの投稿をしておきながら、実はこういうシミュレーションをRでやったことはなかったのですが・・・面白いですね!

Windows版Rでは、グラフィカルなコンソール(Rgui)はコンソール出力のオーバーヘッドがものすごく大きいので、テキストベースのコンソール(Rterm)の方で実行するのをお勧めします。

# initial value
target      <- "METHINKSITISAWEASEL"
target.char <- unlist(strsplit(target, ""))
target.len  <- nchar(target)
initial.population <- 300
mutation.number    <- 1
increase.number    <- 3

# make mutation
mutation <- function(s){
   l <- unlist(strsplit(s, ""))
   l[sample(target.len, mutation.number)] <- sample(LETTERS, mutation.number, replace=FALSE)
   paste(l, collapse="")
}

# calc distance between two strings
distance <- function(lhs, rhs=target.char){
   sum(!(unlist(strsplit(lhs, "")) == rhs))
}

# setup the first population
strings <- replicate(initial.population, paste(sample(LETTERS,target.len, replace=FALSE), collapse=""))

# main routine
while(strings[1] != target){
   strings <- sapply(rep(strings, increase.number), mutation)
   strings <- head(strings[sort.list(sapply(strings, distance))], initial.population)
   print(data.frame(str=head(strings), dist=sapply(head(strings), distance)))
}