Golfing A Weasel Program

APL (143)

0{⍵≢T←'METHINKS IT IS LIKE A WEASEL':c∇⍨1+⍺⊣⎕←(⍕⍺),':'c'-- score:',s⊣c←⊃c/⍨G=s←⌈/G←{+/⍵=T}¨c←{⍵{⍵:⍺⋄C[?27]}¨9≠?28/20}¨100⍴⊂⍵}⊃∘(C←27↑⎕A)¨?28/27

Explanation:

  • 0{...}⊃∘(C←27↑⎕A)¨?28/27: set C to the first 27 capital letters. There are only 26, so the 27th element will be a space. Select 28 random items from C. This will be the first . The first (generation) will be 0.

  • ⍵≢T←'METHINKS IT IS LIKE A WEASEL: set T to the string 'METHINKS IT IS LIKE A WEASEL'. As long as is not equal to T:

    • {...}¨100⍴⊂⍵: Make 100 copies of . For each of these...
      • 9≠?28/20: select 28 random numbers from 1 to 20. Make a bitmask where each 1 means that the random number was not equal to 9. (This means 5% chance of a 0).
      • ⍵{⍵:⍺⋄C[?27]}¨: for each letter in , if the corresponding bit was 1, keep that letter, otherwise replace it with a randomly chosen element from C.
    • c←: store the 100 mutated strings in c.
    • G←{+/⍵=T}¨c: for each element in c, calculate the score (amount of characters that match T) and store the scores in G.
    • s←⌈/G: find the maximum score and store that in s.
    • c←⊃c/⍨G=s: select the first item from c whose score is equal to s (the maximum), and store it in c again.
    • ⎕←(⍕⍺),':'c'-- score:',s: print the generation in the given format ( is current generation, c is current best string, s is score)
    • c∇⍨1+⍺: Increment the generation and run the mutation again using the current best string (c) as input.

Mathematica - 238 236 225

c:="@"~CharacterRange~"Z"~RandomChoice~28/."@"->" "
For[s=""<>c;i=0,{d,s}=Sort[{#~HammingDistance~"METHINKS IT IS LIKE A WEASEL",#}&@
StringReplace[s,_/;20Random[]<1:>c〚1〛]&~Array~100]〚1〛;
d>0Print[i++,":"s," -- score: ",28-d],]

Example output

0:  CYPMEIHADXRXVTFHERYOZNRVFCSQ  -- score: 0
1:  CYPMEIHADIRXVTFBERYOZNRVFCSQ  -- score: 1
2:  CYPMEIHA IRXVTFBIRYOZNRVFCSQ  -- score: 3
...
50:  METHINKS IT IS LIKE A WEASEL  -- score: 28

Python (273)

from random import choice as c
n=range
a=map(chr,n(65,91)+[32])
s=map(c,[a]*28)
p=x=0
while p<28:
 p,s=max((sum(g==r for g,r in zip(y,'METHINKS IT IS LIKE A WEASEL')),y)for y in ([c(a+[x]*513)for x in s]for _ in n(100)));print '%d: %s -- score: %d' % (x,''.join(s),p);x+=1