#import system. #import system'routines. #import extensions. #symbol Target = "METHINKS IT IS LIKE A WEASEL". #symbol AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ". #symbol C = 100. #symbol P = 0.05r. #symbol rnd = randomGenerator. #symbol randomChar = AllowedCharacters @ (rnd nextInt:(AllowedCharacters length)). #class(extension) evoHelper { #method randomString = 0 repeat &till:self &each:x [ randomChar ] summarize:(String new) literal. #method fitness &of:s = self zip:s &into:(:a:b)[ (a == b)iif:1:0 ] summarize:(Integer new) int. #method mutate : p = self select &each: ch [ (rnd nextReal <= p) iif:randomChar:ch ] summarize:(String new) literal. } #class EvoAlgorithm :: Enumerator { #field theTarget. #field theCurrent. #field theVariantCount. #constructor new : s &of:count [ theTarget := s. theVariantCount := count int. ] #method get = theCurrent. #method next [ ($nil == theCurrent) ? [ theCurrent := theTarget length randomString. ^ true. ]. (theTarget == theCurrent) ? [ ^ false. ]. #var variants := Array new:theVariantCount set &every:(&index:x) [ theCurrent mutate:P ]. theCurrent := variants array sort:(:a:b) [ a fitness &of:Target > b fitness &of:Target ] getAt:0. ^ true. ] } #symbol program = [ #var attempt := Integer new. EvoAlgorithm new:Target &of:C run &each:current [ console writeLiteral:"#":(attempt += 1) &paddingLeft:10 writeLine:" ":current:" fitness: ":(current fitness &of:Target). ]. ].