68 lines
1.5 KiB
Text
68 lines
1.5 KiB
Text
import system'routines.
|
|
import extensions.
|
|
|
|
const Target = "METHINKS IT IS LIKE A WEASEL".
|
|
const AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ".
|
|
|
|
const C = 100.
|
|
const P = 0.05r.
|
|
|
|
rnd = randomGenerator.
|
|
|
|
randomChar
|
|
= AllowedCharacters[rnd nextInt(AllowedCharacters length)].
|
|
|
|
extension evoHelper
|
|
{
|
|
randomString
|
|
= 0 till:self repeat(:x)( randomChar ); summarize:(String new); literal.
|
|
|
|
fitnessOf:s
|
|
= self zip:s by(:a:b)( (a == b)iif(1,0) ); summarize(Integer new); int.
|
|
|
|
mutate : p
|
|
= self selectBy(:ch)( (rnd nextReal <= p) iif(randomChar,ch) ); summarize(String new); literal.
|
|
}
|
|
|
|
class EvoAlgorithm :: Enumerator
|
|
{
|
|
object theTarget.
|
|
object theCurrent.
|
|
object theVariantCount.
|
|
|
|
constructor new : s of:count
|
|
[
|
|
theTarget := s.
|
|
theVariantCount := count int.
|
|
]
|
|
|
|
get = theCurrent.
|
|
|
|
next
|
|
[
|
|
if ($nil == theCurrent)
|
|
[ theCurrent := theTarget length; randomString. ^ true ].
|
|
|
|
if (theTarget == theCurrent)
|
|
[ ^ false ].
|
|
|
|
var variants := Array new:theVariantCount; populate(:x)( theCurrent mutate:P ).
|
|
|
|
theCurrent := variants array; sort(:a:b)( a fitnessOf:Target > b fitnessOf:Target ); getAt:0.
|
|
|
|
^ true.
|
|
]
|
|
}
|
|
|
|
program =
|
|
[
|
|
var attempt := Integer new.
|
|
EvoAlgorithm new:Target of:C; forEach(:current)
|
|
[
|
|
console
|
|
printPaddingLeft(10,"#",attempt append:1);
|
|
printLine(" ",current," fitness: ",current fitnessOf:Target).
|
|
].
|
|
|
|
console readChar.
|
|
].
|