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