RosettaCodeData/Task/Evolutionary-algorithm/Scala/evolutionary-algorithm.scala

38 lines
1.3 KiB
Scala

import scala.annotation.tailrec
case class LearnerParams(target:String,rate:Double,C:Int)
val chars = ('A' to 'Z') ++ List(' ')
val randgen = new scala.util.Random
def randchar = {
val charnum = randgen.nextInt(chars.size)
chars(charnum)
}
class RichTraversable[T](t: Traversable[T]) {
def maxBy[B](fn: T => B)(implicit ord: Ordering[B]) = t.max(ord on fn)
def minBy[B](fn: T => B)(implicit ord: Ordering[B]) = t.min(ord on fn)
}
implicit def toRichTraversable[T](t: Traversable[T]) = new RichTraversable(t)
def fitness(candidate:String)(implicit params:LearnerParams) =
(candidate zip params.target).map { case (a,b) => if (a==b) 1 else 0 }.sum
def mutate(initial:String)(implicit params:LearnerParams) =
initial.map{ samechar => if(randgen.nextDouble < params.rate) randchar else samechar }
@tailrec
def evolve(generation:Int, initial:String)(implicit params:LearnerParams){
import params._
printf("Generation: %3d %s\n",generation, initial)
if(initial == target) return ()
val candidates = for (number <- 1 to C) yield mutate(initial)
val next = candidates.maxBy(fitness)
evolve(generation+1,next)
}
implicit val params = LearnerParams("METHINKS IT IS LIKE A WEASEL",0.01,100)
val initial = (1 to params.target.size) map(x => randchar) mkString
evolve(0,initial)