challenge METHINKS IT IS A WEASEL

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

参考

Posted feedbacks - Scala

3だと収束しないので5で。

 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
import scala.util.Sorting.stableSort
class Weasel(val target:String) {
  val rnd = new Random
  val len = target.size
  val chars = (65 to 90).map(_.asInstanceOf[char])
  def newchar = chars(rnd.nextInt(chars.size))

  def similarity(s:String) = (len /: (0 until len)){(r,i) => 
    r-(if(target(i) == s(i)){1}else{0})
  }

  def sort(lst:Seq[String]) = stableSort(lst, similarity _).toList

  def mutate(s:String) = (1 to 5).map{x=> 
    var a = s.toArray
    a(rnd.nextInt(len)) = newchar
    a.mkString("")
  }
 

  def start = {
    val lst = sort((1 to 300).map(x=>(1 to len).map(y=>newchar).mkString("")))
    def iter(ss:List[String], generation:int):unit = {
      printf("Generation %d\n%s\n%s\n\n", generation, "-"*40, ss.take(5).mkString("\n"))
      ss match {
        case head::rest if head == target => ()
        case x => 
          iter(sort(x.flatMap(mutate)).take(300), generation+1)
      }
    }
    iter(lst, 0)
  }
}

new Weasel("METHINKSITISAWEASEL").start

Index

Feed

Other

Link

Pathtraq

loading...