RosettaCodeData/Task/Evolutionary-algorithm/Elena/evolutionary-algorithm.elena

77 lines
1.7 KiB
Plaintext

import system'routines;
import extensions;
import extensions'text;
const string Target = "METHINKS IT IS LIKE A WEASEL";
const string AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int C = 100;
const real P = 0.05r;
rnd = randomGenerator;
randomChar
= AllowedCharacters[rnd.nextInt(AllowedCharacters.Length)];
extension evoHelper
{
randomString()
= 0.repeatTill(self).selectBy:(x => randomChar).summarize(new StringWriter());
fitnessOf(s)
= self.zipBy(s, (a,b => a==b ? 1 : 0)).summarize(new Integer()).toInt();
mutate(p)
= self.selectBy:(ch => rnd.nextReal() <= p ? randomChar : ch).summarize(new StringWriter());
}
class EvoAlgorithm : Enumerator
{
object theTarget;
object theCurrent;
object theVariantCount;
constructor new:of(s,count)
{
theTarget := s;
theVariantCount := count.toInt();
}
get() = theCurrent;
bool next()
{
if (nil == theCurrent)
{ theCurrent := theTarget.Length.randomString(); ^ true };
if (theTarget == theCurrent)
{ ^ false };
auto variants := Array.allocate(theVariantCount).populate:(x => theCurrent.mutate:P );
theCurrent := variants.sort:(a,b => a.fitnessOf:Target > b.fitnessOf:Target ).at:0;
^ true
}
reset()
{
theCurrent := nil
}
enumerable() => theTarget;
}
public program()
{
var attempt := new Integer();
EvoAlgorithm.new:Target &of:C.forEach:(current)
{
console
.printPaddingLeft(10,"#",attempt.append(1))
.printLine(" ",current," fitness: ",current.fitnessOf(Target))
};
console.readChar()
}