text:
Golfing A Weasel Program
Richard Dawkins in his book The Blind Watchmaker, describes a Weasel program. The algorithm can be described as follows:

Start with a random string of 28 characters. Valid characters are all upppercase letters, and space.

Make 100 copies of that string, with a 5% chance per character of that character being replaced with a random character.

Compare each new string with the target "METHINKS IT IS LIKE A WEASEL", and give each a score according to the number of letters in the string which are correct and in the correct position.

If any of the new strings has a perfect score (28), halt.

Choose the highest-scoring string from step 3. How you work out a tie is up to you, but only one string may be chosen. Take the chosen string and go to step 2.

The winner will be the shortest code snippet to get to the correct answer while printing the highest-scoring string of each generation in the following format:

If people could help by checking other peoples answers would be very helpful!

Which characters are allowed? Unicode? Lowercase?

Ah, I love Dawkins. Beauty, and feasibility of evolution shown in a simple algorithm.

May step 4 be better replaced with "step 1.5) If the new strings has a perfect score (28), halt" and "step 4) Take the highest scoring string, and go to step 1.5."?  That is, if the initial random string is a winner, need we fan out?

@RobStarling ah, good point. This algorithm seems to assume that you'll never random the target.

I'm a bit confused as to the order of operations here. Is the intent that we make 100 new strings, based on the original string? Or is it 100 new strings, with the first string being based on the original, and each subsequent string based on the previous string? The algorithm description seems to imply the former, while the sample output appears to be of the latter.

Also, +1 to @Oriol - do we have to use all-uppercase characters or can we do it in all-lowercase? What about mixed case?

its the latter @lszi

@Oriol it's just the 26 (capital) letters, and a space.

@Noelkd The wording definitely implies the former. You should probably edit the question to make this more clear. It does say "Make 100 copies of this string"

@Cruncher it makes sense if you read it in the correct order. If you read 4. then go to 2. The "This" is refering to the string you are taking from step four. Not got any great reason to defend the steps as they were simply copied and pasted from wikipedia, if you feel it would read better with an edit feel free to make that edit.

@Noelkd At step 2 (whether your come from step 1 or 4) says to create 100 copies of the same string(with the random mutations). What Iszi was asking is if, you only make a copy of it once, then the other 99 are chained down from that.

Some solutions at Rosetta Code: Evolutionary algorithm

@Cruncher thanks for taking the time to explain, I really wasn't getting that. The 100 mutations are all mutations of the string you took with you into step two. So if you have a string "hello world" and all the mutations would be based of "hello world" for that generation, if that makes sense?

Yes, that makes sense, and was my interpretation of the problem. @Iszi did say while the sample output appears to be of the latter. I'm not sure where that conclusion came from though.

@Cruncher & Noelkd - Maybe I'm confused as to what the output should be, then. When it says "printing each generation" does it mean we should print all 100 strings that are generated each time the algorithm loops, or only the one that is going to be fed into the next loop? Assuming that the 100 copies for each round are based off of the initial seed, the output sample appears to be of only the seed strings plus the final perfect string.

I'd like to move this discussion to chat for some lengthier clarification.

The instructions are pretty clear, but what if the original string is the target?

When do we print the string? Does the originally generated string get printed, or only after running the algorithm on it once? (If it's the latter, I can save a lot of code)

How you work out a tie is up to you, but only one string may be chosen. seems we can choose any lower score when a tie appear

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.

Explanation?  This looks like alphabet soup! :)

@ToastyMallows: added explanation

Best answer so far, great to have an explaination with it.

@marinus Are you a wizard?

Bullcrap, you just opened MS Word and used WingDings font

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

Python: 282 characters no semi colons
from random import*
g,r,l,c=0,0,"ABCDEFGHIJKLMNOPQRSTUVWXYZ ",choice
k=map(c,[l]*28)
while(r!=28):
 r,k=max((sum(i==j for i,j in zip(t,"METHINKS IT IS LIKE A WEASEL")),t)for t in[[c(l)if random()<.05 else i for i in k]for i in[1]*100])
 print`g`+":","".join(k),"-- score:",`r`
 g+=1

278 with:
from random import*;g,r,l,c=0,0,"ABCDEFGHIJKLMNOPQRSTUVWXYZ ",choice;k=map(c,[l]*28)
while(r!=28):r,k=max((sum(i==j for i,j in zip(t,"METHINKS IT IS LIKE A WEASEL")),t)for t in[[c(l)if random()<.05 else i for i in k]for i in[1]*100]);print`g`+":","".join(k),"-- score:",`r`;g+=1

You should explicitly state the language and since the question is tagged code-golf, you should provide a character count.

Will do, thanks for the tips tim.

Also, you should use all one letter variable names to decrease the character count further.

Waiting till later to golf it down some more, still got some easy wins. Thanks.

In second block loop header and body may by placed in same line: while 1:r=max([(... (result size 355 characters)

Change import * to import*

@timtech I did't know you could do that, 1 more character down!

Is it really supposed to start with all same letters? :)

@JoachimIsaksson fixed it just for you!

You could save a few characters by assigning directly to s rather than k, and by doing "".join only when printing (and working on lists the rest of the time).

great tips, have updated the answer

R (245 239 238 characters)
t=strsplit("METHINKS IT IS LIKE A WEASEL","")[[1]]
h=sample
s=h(f<-c(LETTERS," "),28,T)
c=0
while(!all(s==t)){for(i in 1:100){z=ifelse(runif(28)<.05,h(f,1),s)
y=sum(s==t)
if(sum(z==t)>y)s=z}
cat(c<-c+1,": ",s," -- score: ",y,"\n",sep="")}

Gives:
1: HSSSIMJM ETJISGBSCIELUYPLSED -- score: 7
2: HSSSIMJM ETJISGBSKIELUYPLSED -- score: 8
3: EETLITLM ETJISTBSKIELUYLLSEL -- score: 11

...
78: METHINKS IT IS LIKEEA WEASEL -- score: 27
79: METHINKS IT IS LIKEEA WEASEL -- score: 27
80: METHINKS IT IS LIKEEA WEASEL -- score: 27
81: METHINKS IT IS LIKE A WEASEL -- score: 28

how to you get your first line 0: ... if the first time you invoke cat you increment c to 1? (+1 nonetheless as i m trying since an hour to do something shorter and i still can't :) )

@plannapus That is true, was from an old version (which was somewhat longer). Either I change it to -1 in the beginning, or use 1 in the first line...

I see two problems with your code. First, this ifelse(…,h(f,1),…) replaces all selected positions with the same random char. You can interpret the rules in this direction, but it feels like bending them so I'd at least mention it. Second, you replace s=z within the 1:100 loop, so you are not making 100 copies of the same string, but sometimes copies of a copy. This seems like breaking a rule to mee, not merely bending it.

K,  173 167
o:"METHINKS IT IS LIKE A WEASEL"
i:0;{~x~o}{-1($i),": ",(r:a@*&b=c)," -- score: ",$c:max@b:+/'o=/:a:{x{if[0~*1?20;x[y]:*1?s];x}/!#x}'100#,x;i+:1;r}/28?s:"c"$32,65+!26;

/
0: FQRZPHACDIBHZOUUCYKKFBJWVNVI -- score: 1
1: FQRZP ACDITHCOUUCYKKFBJWVNVI -- score: 2
2: FQRZP AFDIT COUUCYKKFBJWVNVI -- score: 3
...
51: METHINKS IT IS LIKECA WEASEL -- score: 27
52: METHINKS IT IS LIKECA WEASEL -- score: 27
53: METHINKS IT IS LIKE A WEASEL -- score: 28

JavaScript, 277 246
c=m=>" ABCDEFGHIJKLMNOPQRSTUVWXYZ"[0|Math.random()*m];for(s=[k=28];e=k;s[--k]=c(27));for(;alert(k+++": "+s.join("")+" -- score: "+e),e<28;s=t)for(z=100;f=0,z--;f>e&&(t=n,e=f))n=s.map((h,p)=>(h=c(540)||h,f+=h=="METHINKS IT IS LIKE A WEASEL"[p],h))

(requires arrow function support; indentation added only for readability)
// c() returns a random char using `m` as an index max
c=m=>" ABCDEFGHIJKLMNOPQRSTUVWXYZ"[0|Math.random()*m];

// generate base string `s`
for(s=[k=28];e=k;s[--k]=c(27));

// while score `e` is < 28
for(;alert(k+++": "+s.join("")+" -- score: "+e),e<28;s=t)
    for(z=100;f=0,z--;f>e&&(t=n,e=f))            // do 100 mutations; keep best score
        n=s.map((h,p)=>(                         // map `s` to `n` with 5% mutation
            h=c(540)||h,                         // change the char in 5% of cases
            f+=h=="METHINKS IT IS LIKE A WEASEL"[p],  // score++ if char matches
            h                                    // arrow function return character
        ))

Feel free to change alert to console.log if you want a more pleasant execution experience.
There are some nifty golfy bits in here:

The function c returns a random character from the alphabet string " ABC...". The function takes an argument to use as an upper bound for the random index selection. When generating the base string, we use 27, so the function behaves normally.
However, we abuse this behavior by asking for a random upper bound of 540 in h = c(540) || h. Only 5% of the time will c actually return a string (because 540 * .05 = 27); the other 95% of the time, the randomly-chosen index falls beyond the length of the string, so the function returns undefined. This falsey value causes a logical-OR cascade in c(540) || h, so the original map value h is used (i.e., no replacement occurs).

The score-summing operation does f+=h=="METHINKS IT IS LIKE A WEASEL"[p], which says "add true to f if the current map character h matches the pth character of the WEASEL string". The number-plus-boolean addition coerces the boolean result to either 0 or 1, which means that f is incremented only when there is a match against the target WEASEL string.

Why have you got v stated in the code? It's not mentioned anywhere else in there. You can save yourself 2 chars.?

@Eliseod'Annunzio v is an argument to the arrow function stored in c: c = (v => ...). If you want to define an arrow function without arguments, it costs two characters, ()=>... , instead of one, v=>..., so it's better to simply have an unused argument.

Clever use of code!

Nice trick with k=s=[28] and ++, I had no idea!

C 256
char c[101][29],s,n,z,b,j,i,w;g;main(){for(;w<28;printf("%d: %s -- score: %d\n",g++,c[b=n],w))for(i=w=0;i<101;i++)for(s=j=0;j<28&&!(i==b&&g);j++)(s+=(c[i][j]=g&&rand()%20?c[b][j]:(z=rand()%27)?'A'+z-1:' ')=="METHINKS IT IS LIKE A WEASEL"[j])>w?n=i,w=s:0;}

Simple three loops, initialization, generation of new strings from parent and score calculated by the same statement. It's not very readable even with indentation.
C 252
i,g,n,b,o,s,w,z;char c[2929];main(){for(;(o=i%29)|i|w<28;(i=(i+1)%2929)||printf("%d: %s -- score: %d\n",g++,&c[b=n],w))(s+=o>27?-s:((i-o!=b||!g)&&(c[i]=g&&rand()%20?c[b+o]:(z=rand()%27)?'A'+z-1:' ')=="METHINKS IT IS LIKE A WEASEL"[o]))>w?n=i-o,w=s:0;}

One loop, with one array holding all 101 strings.
This second version breaks the rules because it prints the string from (the equivalent of) step 1, but it was either that or not print the last string. I'm stumped how to fix it without exploding in size. I'm posting it anyway for inspiration.
C 256
struct{char d[29];}p,t,n;i,j=-1,z,s,w,g;main(){for(;w<28;j>1&&printf("%d: %s -- score: %d\n",g++,(p=n).d,w))for(;j++%100;p=j?p:t)for(s=0,i=28;i--;)(s+=(t.d[i]=j&&rand()%20?p.d[i]:(z=rand()%27)?'A'+z-1:' ')=="METHINKS IT IS LIKE A WEASEL"[i])>w?n=t,w=s:0;}

Different approach, instead of making an array to hold 101 strings just regenerate the string 100 times and use struct assignment for easy copying. Initialization is done by starting the "repeat 100 times" counter at -1 and handling it carefully by strategically chosen post-increment. Despite a very different approach it ends up exactly the same as the first attempt - 256 characters.

C# - 436
namespace System.Linq{class W{static void Main(){var r=new Random();
Func<char>c=()=>(char)(r.Next(33,60)%59+32);var s="";
while(s.Length<28)s+=c();var a="METHINKS IT IS LIKE A WEASEL";int b=0;
while (s!=a){int m=-1;var f=s;for(int i=0;i<100;i++){
var l=string.Join("",s.Select(j=>(r.Next(20)!=0?j:c()).ToString()));
int o=Enumerable.Range(0,28).Sum(j=>l[j]==a[j]?1:0);if(o>m){f=l;m=o;}}
Console.WriteLine(b+++": "+(s=f)+" -- score: "+m);}}}}

This is broken. You need using System; or manually qualifying System.

No, you don't. http://ideone.com/4alNSi.

Ah nice. Looked at the NS declaration as a using sorry.

Lua 5.1 (502)
The minimised version:
s,t,b,c,i,q,a,d,f="ABCDFGHJYUEGKSHNCOLPQIEJUSNC","METHINKS IT IS LIKE A WEASEL",1,math.random,table.insert,1,string.sub,100,28 while q~=f do r,p={},{} for x=1,d do i(r,s) i(p,0) e="" for o=1,f do if c(1,20)==1 then if c(1,27)==1 then e=e.." " else e=e..string.char(c(65,90)) end else e=e..a(r[x],o,o) end end r[x]=e for y=1,f do if a(r[x],y,y)==a(t,y,y) then p[x]=p[x]+1 end end if p[x]==f then s=r[x] end end for x=1,d do if p[x]>=q then s,q=r[x],p[x] end end print(b..":",s,"-- score: "..q) b=b+1 end

and the easier to read version (with comments!):
s,t,b,c,i,q,a,d,f="ABCDFGHJYUEGKSHNCOLPQIEJUSNC","METHINKS IT IS LIKE A WEASEL",1,math.random,table.insert,1,string.sub,100,28
--s=random string, t=target, b=counter, c=reference to math.random, i=reference to table.insert, q=top score,a=reference to string.sub, d=constant (100), f=constant (28)
while q~=f do
    r,p={},{}
    for x=1,d do  --add 100 copies to the table of strings
        i(r,s)
        i(p,0)
        e=""
        for o=1,f do  --for each character in string
            if c(1,20)==1 then  -- 5% chance
                if c(1,27)==1 then e=e.." " else e=e..string.char(c(65,90)) end  --set it to an ASCII char between 65 and 90 (A-Z) or a space character
            else
                e=e..a(r[x],o,o)
            end
        end
        r[x]=e  --current string = mutations
        for y=1,f do
            if a(r[x],y,y)==a(t,y,y) then p[x]=p[x]+1 end
        end  --for each char increment score if it is correct
        if p[x]==f then
            s=r[x]
        end  --if 28 then final string is this!
    end
    for x=1,d do
        if p[x]>=q then s,q=r[x],p[x] end  --if this is the highest score so far, then make the string equal to this
    end
    print(b..":",s,"-- score: "..q)  --print it!
    b=b+1  --add one to the counter!
end

To be honest even though this definitely won't win, I was just glad to find and minimise a reasonably short solution for this problem! (emphasis on reasonably) :p

Scala, 347 341 337 chars:
import util.Random.{nextInt=>r}
val t="METHINKS IT IS LIKE A WEASEL"
def c="ABCDEFGHIJKLMNOPQRSTUVWXYZ "(r(27))
def s(a:String)=t.zip(a).map{x=>if(x._1==x._2) 1 else 0}.sum
def w(a:String,i:Int=0){println(f"$i%2d: $a -- score: ${s(a)}")
if(s(a)!=28){w((0 to 99).map{_=>a.map(o=>if(r(20)<1) c else o)}.sortBy(s).last,i+1)}}
w(t.map(_=>c))

=>
 0: PGSHWAEPALQFTCORUKANPNUTRVXH -- score: 2
 1: PGSHWAEPALQ TCOQUKANPNUTRVXH -- score: 3
...
47: METHINKS WT IS LIKE A WEASEL -- score: 27
48: METHINKS IT IS LIKE A WEASEL -- score: 28

oops. i misread the algorithm and instead of "a 5% chance per character of that character being replaced with a random character", i had permuted a single random character. will fix.

fixed and trimmed a little!

in scala 2.10, println("%2d: %s -- score: %d".format(i,a,s(a)) can change to println(f"$i%2d: $a%s -- score: ${s(a)}%d"), saving 4 chars!

((('A'to'Z')toSeq):+' ') == "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", and the 2 %s are not necessary for printing string, saving 9 chars

@Chris what version of scala did you run that under? def c=(' '+:('A'to'Z'))(r(27)) gives me error: type mismatch;  found   : Int  required: scala.collection.generic.CanBuildFrom[scala.collection.immutable.IndexedSeq[Char],Char,?]

reverted the range. good call on the dropped %ss. wasn't clear from the docs that that'd work.

ah. "If there is no % character after a variable definition a formatter of %s (String) is assumed." per http://docs.scala-lang.org/overviews/core/string-interpolation.html

oh, neat. ideone is fun: http://ideone.com/QFnJW8

SAS - 374
%macro r;ranuni(7)%mend;%macro s;r=int(%r*27);substr(x,t,1)=byte(ifn(r,64+r,32));%mend;%macro y;char(y,t)=char(x,t)%mend;options nonotes nosource;data x;length x$28;do t=1to 28;%s;end;y="METHINKS IT IS LIKE A WEASEL";do z=1by 1;o=x;do i=1to 100;c=0;x=o;do t=1to 28;if %r<=.05then do;%s;end;c+%y;end;if c>m then do;m=c;v=x;end;end;x=v;put z":" x"-- score:" m;if m<28;end;run;

->
1 :GUUVLNUSILSRZLRBXVVCWXX HXKC -- score:2
2 :MUUVLNUSILSRZLRBXVMCWXX HXKC -- score:3
3 :MUUVLNESILSRILRBXVMCWXX HXKC -- score:4
4 :MEUVLNESILSRIRRBXVMCWXX HXKC -- score:5
....
95 :METHINKS IT IS LIKE A XEASEL -- score:27
96 :METHINKS IT IS LIKE A XEASEL -- score:27
97 :METHINKS IT IS LIKE A XEASEL -- score:27
98 :METHINKS IT IS LIKE A WEASEL -- score:28

With linebreaks/indent/comments:
%macro r;
 ranuni(7)   /* seed 0 will make new each time (seed=clock), otherwise fixed results */
%mend;
%macro s;  /* does the rand char, used both to initialize and replace; */
 r=int(%r*27);
 substr(x,t,1)=byte(ifn(r,64+r,32)); *r=0 becomes space otherwise upper char;
%mend;
%macro y;  /*compares using new to 9.2 CHAR function which is equivalent to substr(str,start,1) */
 char(y,t)=char(x,t)
%mend;
options nonotes nosource; /*cheapest way to get clean log */
data x;
 length x$28; /*annoyingly necessary*/
 do t=1to 28;%s;end; /*initialize string*/
 y="METHINKS IT IS LIKE A WEASEL"; /*compare string */
 do z=1by 1; /*start iterating */
  o=x; /*save this iteration's string */
  do i=1to 100;
   c=0; /*score for this iteration*/
   x=o; /*string to fudge about start out clean, reusing x so no params to macro*/
   do t=1to 28;
    if %r<=.05then do;%s;end; /*if 5% then change the char out */
    c+%y; /*score that character*/
   end;
   if c>m then do; /*if on better scoring line, save it */
    m=c;
    v=x;
   end;
  end;
  x=v; *for next iter - this is cheaper than other options involving o=v due to first iter;
  put z":" x"-- score:" m;
  if m<28; *quit at 28;
 end;
run;

C 361 331
Not as good as Art's solution, but here's my (newbie) attempt at a C solution. 361 characters if you remove newlines and tabs.
char*w="METHINKS IT IS LIKE A WEASEL";char b[101][29];t,s,n,i,j,x,a;main(){for(;i<28;i++)b[0][i]=w[rand()%28];while(s<28){for(j=1;j<101;j++){x=0;for(i=0;i<28;i++){if(!(rand()%20))b[j][i]=w[rand()%28];else b[j][i]=b[0][i];if(b[j][i]==w[i])x++;}if(x>s){s=x;t=j;}}printf("%d: %s -- score %d\n",n++,b[t],s);for(;i>=0;--i){a=b[0][i];b[0][i]=b[t][i];b[t][i]=a;}t=0;}}

Edit: Got rid of the nested loop and used a 1D array. Was hoping it would make a bigger difference, but it only saved me 30 characters. Here's the code:
char*w="METHINKS IT IS LIKE A WEASEL";char b[2929];t,s,n,i,x;main(){for(;i<28;i++)b[i]=w[rand()%28];while(s<28){for(;i<2929;i++){if((i+1)%29){if(!(i%29))x=0;b[i]=rand()%20?b[i%29]:w[rand()%28]; x+=b[i]==w[i%29];if(x>s){s=x;t=i/29;}}}for(i=0;i<29;i++){x=b[i+t*29];b[i+t*29]=b[i];b[i]=x;}printf("%d: %s -- score %d\n",n++,b,s);t=0;}}

Edit: This is the original, ungolfed code, for those who are interested in knowing how the "golfing" was done. The code produces no warnings when compiled with GCC with -Wall and C99 enabled. Maybe you're a golfing newbie like me, or a C newbie like me, or maybe you're just curious. :) https://gist.github.com/cpx/97edbce4db3cb30c306a

PHP 442
<? function r(){$n=rand(65,91);if($n==91) return ' ';else return chr($n);}function s($s){$c=0;$t='METHINKS IT IS LIKE A WEASEL';for($i=0;$i<28;$i++) if($s[$i]==$t[$i]) $c++;return $c;}function m($s){for($i=0;$i<28;$i++) if(rand(0,99)<5) $s[$i]=r();return $s;}$s='';for($i=0;$i<28;$i++) $s.=r();for($i=0;;$i++){$l=s($s);printf("%2d: %s -- score: %d\n",$i,$s,$l);if($l==28) break;$x=$s;for($j=0;$j<100;$j++){$t=m($s);if(s($t)>$l) $x=$t;}$s=$x;}

Readbly:
<?
//random char
function r(){
    $n=rand(65,91);
    if($n==91) return ' ';
    else return chr($n);
}
//score
function s($s){
    $c=0;
    $t='METHINKS IT IS LIKE A WEASEL';
    for($i=0;$i<28;$i++)
        if($s[$i]==$t[$i]) $c++;
    return $c;
}
//mutate
function m($s){
    for($i=0;$i<28;$i++)
    if(rand(0,99)<5) $s[$i]=r();
    return $s;
}
$s='';
for($i=0;$i<28;$i++) $s.=r();
for($i=0;;$i++){
    $l=s($s);
    printf("%2d: %s -- score: %d\n",$i,$s,$l);
    if($l==28) break;
    $x=$s;
    for($j=0;$j<100;$j++){
        $t=m($s);
        if(s($t)>$l) $x=$t;
    }
    $s=$x;
}

removing extra whitespace after if\for, it is at 436. you could also check $n>90 for another char

I like this, it's actually readable.  I've found a few possible improvements to your r() and s() functions.  Here's the changes with comments: http://ideone.com/4ecZQc

Oh, and your printf statement can be shortened.  The %s is always the same length and the %d is left justified, so you can use the following instead: printf("%2d: $s -- score: $l\n",$i);

Python (330 321)
def b(i,s):print i,':',''.join(s),'-- score:',p(s)
from random import*;a=" ABCDEFGHIJKLMNOPQRSTUVWXYZ";i,s,t=0,choice(a)*28,"METHINKS IT IS LIKE A WEASEL";p=lambda n:sum(n[c]==t[c]for c in range(28))
while p(s)<28:b(i,s);s=sorted([[(c,choice(a))[random()<.05]for c in s]for k in[1]*100],key=lambda n:p(n))[-1];i+=1
b(i,s)

Readable version:
def b(i,s):
    print i,':',''.join(s),'-- score:',p(s)

import random as r
a=" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
i,s,t=0,r.choice(a)*28,"METHINKS IT IS LIKE A WEASEL"
p=lambda n:sum(1for c in range(28)if n[c]==t[c])
while p(s)<28:
    b(i,s)
    s=sorted([[(c,r.choice(a))[r.random()<.05]for c in s]for k in[1]*100],key=lambda n:p(n))[-1];i+=1
b(i,s)

Example output:
0 : SSSSSSSSSSSSSSSSSSSSSSSSSSSS -- score: 3
1 : SSSQSSSSSSSSSSSSISSSSSSSSSSS -- score: 4
2 : SSSQISSSSSSSSSSSISSSSSSSSSSS -- score: 5
3 : SSSQISSSSSSSSSSSIKSSSSSSSSSS -- score: 6
4 : SMSQISSSSSSSISSSIKSSSSGSSSSS -- score: 7
...
53 : METHINKS IT IS UIKE A WEASEL -- score: 27
54 : METHINKS IT IS UIKE A WEASEL -- score: 27
55 : METHINKS IT IS LIKE A WEASEL -- score: 28

edit: removed a few characters based on AMKs and Timtechs answer

sum(1for c in range(28)if n[c]==t[c]) may be shortened to sum(n[c]==t[c] for c in range(28)) (-3 chars)

Save 5 chars, change import random as r to from random import* and then remove the three instances of r.

Sorry, I don't speak Python. Is line zero in your sample output just a freak coincidence or does your script always start with all S's? The challenge requires starting with a string of random characters.

It starts with 28 random character, but they are always the same.

@Iszi Lol, it never said that each individual character had to be random! PsHegger: lol starting with all S's is fitting for the name of your language ;)

@PsHegger Then I'm sorry but you'll have a down-vote from me until that gets fixed. I don't see how "Start with a random string of 28 characters." can be construed to permit strings that are all one character, except for the extremely rare case when 28 random picks all come out the same.

@Iszi: I don't really understand your problem, all I had to do is generating a random string to start from. My code does exactly this, having all As is just as random as any other starting string

@PsHegger Provided that each A is the result of an independent, random choice then your statement is true. However, if your code will never generate starting strings like HHHMWVKPHWBNXPCHXLDSYJRW XRB then it is not really generating "random strings of 28 characters".

@Iszi in my interpretation if it is not starting with the same sequence of characters on every run, but chooses from a finite set of predefined strings it is random. The only difference is the number of predefined strings which is 27 in my program, but 27ˆ28 for you. Although my code has less options to choose the starting string from it starts with one. Also as Darknob of Snow stated the question only asked for a random starting string, and in my opinion, if I use a random number generator to create that string it is acceptable.

Using an RNG to create the string is not an issue at all. It's how that RNG is used which could be. Taken to PowerShell, the difference between your interpretation and mine is the difference between $x=([string][char](65..90+32|random))*28 versus 1..28|%{$x+=[char](65..90+32|random)}. The former picks one random character and repeats it 28 times. The latter picks 28 random characters. I'll give you credit for the justification of rule-stretching - down-vote removed - but I'm not sure I'll pop an up-vote for that. (I'll need you to edit the answer so I can pull the down-vote.)

Perl 5, 219 bytes
$_="METHINKS IT IS LIKE A WEASEL";sub r{(A..Z,$")[rand 27]};sub t{~~grep/$t[$-++%28]/,pop=~/./g}$}.=r for@t=/./g;printf"%3d: %s -- score: %d
",$i++,(($})=sort{t($b)<=>t$a}map s/./rand>.05?$&:r/ger,($})x100),t$}until/$}/

Try it online!

Ruby - 225 202 203 198 chars
Ruby seems under-represented in this challenge so far so I thought I would give it a try!  Improvements welcome.
g=-1
s=[]
puts"#{g+=1}: #{$.,s=(0..99).map{n=(r=0..27).map{|i|x=[' ',*?A..?Z].sample;rand<0.05?x:s[i]||=x};[r.count{|i|n[i]=='METHINKS IT IS LIKE A WEASEL'[i]},n*'']}.max;s} -- score: #$."until$.>27

In your output, "generation #" begins at 1 but the question specifies 0. If you init with g=-1 then it's fine. There may be a smarter way but I did it that way. Cheers, fellow RubyGolfer.

@DarrenStone Good call, thanks!  Costs a character but I couldn't think of a better way.

By moving the code into the string, you can get to 198 chars: (same first two lines, then this for the rest)
puts"#{g+=1}: #{$.,s=(0..99).map{n=(r=0..27).map{|i|x=[' ',*?A..?Z].sample;rand<0.05?x:s[i]||=x};[r.count{|i|n[i]=='METHINKS IT IS LIKE A WEASEL'[i]},n*'']}.max;s} -- score: #$."until$.>27

Good call! I'll edit it in.

Java (632)
class C {public static void main(String[] a){String b="AAAAAAAAAAAAAAAAAAAAAAAAAAAA";for(int i=1;;i++){String c=w(b);int s=s(c);if(s==28)break;if(s(b)<s){b=c;System.out.println(i+": "+c+" -- score: "+s);}}}public static String w(String b) {StringBuffer c = new StringBuffer(b);int max = 0;for (int i=0;i<100;i++){for(int j=0;j<28;j++)if(Math.random()<.06){double d=Math.random();c.setCharAt(j,(char)(d==1?32:d*26+65));}String d=c.toString();int s=s(d);if(s>max){max=s;b=d;}}return b;}public static int s(String s){String b="METHINKS IT IS LIKE A WEASEL";int sum=0;for(int j=0;j<28;j++)sum+=s.charAt(j)==b.charAt(j)?1:0;return sum;}}

Java is such a verbose language.. :(

Ruby, 218
g,s,p,t=-1,'',1;while t!=28;t,b=-1;100.times{|i|m,n='',0
28.times{|j|n+=1if(m[j]=(rand<p ?[*?A..?Z,' '].sample: s[j]))=="METHINKS IT IS LIKE A WEASEL"[j]}
b,t=m,n if n>t};puts"#{g+=1}: #{s=b} -- score: #{t}";p=0.05;end

example run
0: LRAZZMKL IKUOGEHLKPWEVNEAZWX -- score: 6
1: LRAZZMKL IKUIGEALKMWEVNEAZWX -- score: 7
2: HRAGZMKL IKUIGEALKMWEVNEAZWX -- score: 7
3: HVAGZMKL IKUISAALKYWEVNEAZWX -- score: 8
                  ...
48: METHIUKS IT IS LIKEIA WEASEL -- score: 26
49: METHINKS IT IS LIKEIA WEASEL -- score: 27
50: METHINKS IT IS LIKEIA WEASEL -- score: 27
51: METHINKS IT IS LIKE A WEASEL -- score: 28

PHP (381 397 323 319 312):
<? function s(&$s,&$i=0){$t='METHINKS IT IS LIKE A WEASEL';$i=0;$c=$s;$f=28;while($f--){$n=rand(0,26);$i+=($s[$f]=($c=='_'||!rand(0,19)?chr($n?$n+64:32):$s[$f]))==$t[$f];}}$s='_';s($s);$x=$y=0;do{$f=100;while($f--){$m=$s;s($m,$i);if($i>$y){$y=$i;$l=$m;}}printf("%2d: %s -- score: $y\n",$x++,$s=$l);}while($y<28);

Readable version:
<?
function s(&$s, &$i = 0) {
    $t = 'METHINKS IT IS LIKE A WEASEL';
    $i = 0;
    $c = $s;
    $f = 28; while ($f--) {
        $n = rand(0, 26);
        $i += ($s[$f] = ($c == '_' || !rand(0, 19) ? chr($n ? $n + 64 : 32) : $s[$f])) == $t[$f];
    }
}

$s = '_';
s($s);
$x = $y = 0;

do {
    $f = 100; while ($f--) {
        $m = $s;
        s($m, $i);

        if ($i > $y) {
            $y = $i;
            $l = $m;
        }
    }

    printf("%2d: %s -- score: $y\n", $x++, $s = $l);
} while ($y < 28);

Optimization credits (319):

@GigaWatt in this comment
@Einacio for !rand(0,19) taken from here

Optimization credits (312):

@Einacio's comments

i like the joint generator + randomizer

you could change both for for $f=N;while($f--){ for 3 char each. and for another char: $n=rand(0,26);[...]chr($n?$n+64:32)

Generator + randomizer + score computation. :) Thanks, I applied your optimizations.

Ruby, 206 200 199
q,i,*R=*-2..27
puts"#{i+=1}: #{$.,s=(-2..q).map{x=R.map{|j|!s||rand<0.05?[*?A..?Z,' '].sample: s[j]};[R.count{|i|x[i]=='METHINKS IT IS LIKE A WEASEL'[i]},x]}.max;q=97;s.join} -- score: #$."until$.>27

The first line is simply a fancy way to define q=-2, i=-1, and R=(0..27).to_a. All the work is done in the 2nd line:
puts"..."until$.>27 # Prints the string in quotes until we reach the desired score
     ^
     |
 +---+
 |
"#{i+=1}: #{...} -- score: #$."
   ^        ^               ^
   +--------|---------------|-- Generation counter
 +----------+---------------|-- Current string
 |                          +-- Score of current string (interpolates the `$.` variable)
 |
 #{$.,s=(-2..q).map{...}.max;q=97;s.join} # Generate the score & string
   ^         ^  ^   ^    ^   ^    ^
   +---------|--|---|----|---|----|------ Store the score; this variable makes
             |  |   |    |   |    |       string interpolation shorter.
             +--|---|----|---+----|------ `q` automatically takes care of generating
                |   |    |        |        the string vs randomizing the string.
                +---|----|--------|------  Make 100 (or 1 the first time) strings,
                    |    |        |        and compute their score.
                    |    +--------|------- Take the string with the max score.
 +------------------+             +------- `s` is stored as an array
 |
 x=R.map{...};[R.count{...},x] # Compute string and its score, store in array
   ^     ^    ^^       ^
   +-----|----|+-------|------ `R` is 0..27, we use the constant to save chars.
         |    +--------|------ `max` orders by first element, then second. We clearly want
         |             |       the highest score, so make the score first.
 +-------+-------------|------ Generate the string, store in `x`.
 |                     +------ Count the number of chars that overlap with 'METHINKS...'
 |                     |
 |                    {|i|x[i]=='METHINKS IT IS LIKE A WEASEL'[i]}
{|j|!s||rand<0.05?[*?A..?Z,' '].sample: s[j]}
    ^   ^         ^             ^       ^
    +---+---------|-------------|-------|---- 5% chance of randomizing, or 100% for
                  |             |       |     first string.
                  +-------------+-------|---- Sample from alphabet + ' '.
                                        +---- Don't alter the string 95% of the time

@ZachGates Glad you like the commenting style

Japt v2.0a0, 112 108 bytes
ª(T=Si26õdI q¹ö28
_¬í¥`Ú0ˆks Š ‰ ¦ke a Øâel`u q)x
(OpW+`: {U} -- sÖ: `+(K=[U]xV¹WÄ
K<28©ßLÆ®p513 iT ö}ÃñV o

Try it online!
-4 bytes thanks to @ETHproductions.
Unpacked & How it works
U||(T=Si26õdI q) ö28  Initialize primary input
U||                   If U is not initialized...
        26õdI           Generate uppercase alphabets
              q         Convert to string
      Si                Add space
   (T=         )        Assign to variable T
                 ö28    Sample 28 random chars from T and form a string
                        Implicitly assign to U

_q í==`Ú0ˆks Š ‰ ¦ke a Øâel`u q)x  Match counting function
_                                  Declare a function...
 q í==                         )     Convert to array of chars and pair with the next,
                                     and map with equality...
      `Ú0ˆks Š ‰ ¦ke a Øâel`u q        "methinks it is like a weasel" to uppercase
                                        split into chars
                                x    Sum (true == 1, false == 0)
                                   Implicitly assign to V

(OpW+`: {U} -- sÖ: `+(K=[U]xV) W+1  Output and increment counter
(Op                           )      Output with newline...
   W+`: {U} -- sÖ: `+                 `{W}: {U} -- score: `
                         [U]xV         Call V on [U] and force cast to number
                      (K=     )        Assign to K
                                W+1  Add 1 to W and implicitly assign to W

K<28&&ßLo@Um_p513 iT ö}} ñV o  Termination check and recursion
K<28&&                         If the match count is less than 28...
      ß                          Recurse the program with...
          Um_                      Map over chars of U...
             p513 iT                 The char repeated 513 times plus T
                     ö}              Sample a char from it
       Lo@             }           Generate array of 100 of the above
                         ñV o      Sort by V, pop the largest, pass it as U

106 bytes, with a switch to v1.4.5.

Japt -R, 94 bytes
A different approach to but with a little inspiration from Bubbler's solution.
;C±S ö28
È¶`Ú0ks   ¦ke a Øâel`gY
@=#dÆ£20ö ?X:CöÃÃñ_¬xVÃo)Ê¶G}a@Np[X+':Uu '-²`sÖ:`G=U¬xV]¸

Test it (or Try It Online)

Explanation
Line 1
Result gets assigned to variable U.
;C±S ö28
;C           :The lower case alphabet
  ±S         :Append a space and reassign result to C
     ö28     :Generate a string of 28 random characters

Line 2
Result gets assigned to variable V.
È¶`Ú...l`gY
È               :A function that takes 2 arguments; a string (X) and an integer (Y)
  `Ú...l`       :  The compressed string "methinks it is like a weasel"
         gY     :  Get the character at index Y
 ¶              :  Test for equality with X

Line 3
The result of this line is implicitly joined with newlines and output.
@=#dÆ£20ö ?X:CöÃÃñ_¬xVÃo)Ê¥G}a@Np[X+':Uu '-²`sÖ:`G=U¬xV]¸
@                           }a@                            :Repeat until true
                                 [                     ]   :Build an array containing ...
                                  X+':                     :  A colon appended to the number of the current iteration
                                      Uu                   :  The current value of U uppercased
                                         '-²               :  A hyphen repeated twice
                                            `sÖ:`          :  The compressed string "score: "
                                                   U¬      :  Split U to an array of characters
                                                      V    :   Pass each character X at index Y through function V
                                                     x     :   Reduce by addition
                                                 G=        :   Assign the result to variable G
                                                        ¸  :Join with spaces
                               Np                          :Push to N (initially an empty array)
  #d                                                       :100
    Æ                                                      :Generate the range [0,100) and pass each through a function
     £                                                     :  Map over each character X in U
      20ö                                                  :    Generate a random number in the range [0,20), which has a 5% chance of being 0 (falsey)
          ?X                                               :    If thruthy, return X
            :Cö                                            :    Else return a random character from C
               Ã                                           :  End mapping
                Ã                                          :End function
                 ñ_                                        :Sort by passing each through a function
                   ¬                                       :  Split to an array of characters
                     V                                     :  Pass each character X at index Y through function V
                    x                                      :  Reduce by addition
                      Ã                                    :End sorting
                       o                                   :Pop the last element
 =                      )                                  :Reassign to U
                         Ê                                 :Length
                          ¶G                               :Equal to G

Ruby - 410
#!/usr/bin/env ruby
C,RC=[32]+(65..90).to_a,->{C[rand(27)].chr}
T,CO,CH,OU,s,sc,a,aa,z,TR="METHINKS IT IS LIKE A WEASEL",->x{a=0;(0...28).each{|z|a+=1 if x[z]==T[z]};a},->{a[aa.rindex(sc)]},->x,y{print x;print " Score: ";puts y},(0...28).map{RC[]}.join,0,[0],[0],0,->{rand(20)==0}
until sc==28
a=[s]*100;aa=[0]*100;(0...100).each{|x|(0...28).each{|y|a[x][y]=RC[] if TR[]};z=CO[a[x]];aa[x]=CO[a[x]];OU[a[x],z]};sc=aa.max;s=CH[] end

Edit* It's currently failing (for some reason a[any] is being set to 0 (type=>fixnum)). However, the actual design is right, I just need to find the bug causing this to happen (it's very mysterious)

PHP 429 426 421 415
<? function t(){$a="ABCDEFGHIJKLMNOPQRSTUVWXYZ ";return $a{rand(0,26)};}$c='';$j=$g=0;$i=28;while($i--)$c.=t();function r($s){$i=28;while($i--)!rand(0,19)&&$s{$i}=t();return $s;}function s($s,&$r){$c="METHINKS IT IS LIKE A WEASEL";$i=28;$r=0;while($i--)$r+=$s{$i}==$c{$i};}while($g<28){$n='';$v=0;$i=100;while($i--){s($t=r($c),$a);($a>$v)&&($v=$a)&($n=$t);}($v>$g)&&($g=$v)&($c=$n);echo $j++.": $c -- score: $g\n";}

pretty print
<?php
function t(){
    $a="ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
    return $a{rand(0,26)};
}
$c='';
$j=$g=0;
$i=28;
while($i--)
    $c.=t();
function r($s){
    $i=28;
    while($i--)
        !rand(0,19)&&$s{$i}=t();
    return $s;
}
function s($s,&$r){
    $c="METHINKS IT IS LIKE A WEASEL";
    $i=28;
    $r=0;
    while($i--)
        $r+=+($s{$i}==$c{$i});
}
while($g<28){
    $n='';
    $v=0;
    $i=100;
    while($i--){
        s($t=r($c),$a);
        ($a>$v)&&($v=$a)&($n=$t);
    }
    ($v>$g)&&($g=$v)&($c=$n);
    echo $j++.": $c -- score: $g\n";
}

I'll need a less verbose language next time

shortest php answer so far well done!

could be better, but i shoud work

you can always come back and update your answer

Python 284
from random import*
C=choice
A=map(chr,range(65,91)+[32])
s=[C(A)for i in[0]*28]
N=x=0
while N!=28:N,s=max((len([i for i,j in zip(X,"METHINKS IT IS LIKE A WEASEL")if i==j]),X)for X in[[c if random()<.95 else C(A)for c in s]for i in[0]*100]);print`x`+":",''.join(s),"-- score:",N;x+=1

GolfScript 207
{91,{64>},32+''+27rand=}:g;'METHINKS IT IS LIKE A WEASEL':s;{`{\.@\=s@==}+s,,\%{+}*}:c;0:k;{k):k\.': '@@c' -- score: '\++++n+}:f;[{g}]28*{~}%{s=!}{{`100,\{\;{100rand 5>{ }{;g}if}%''+}+}~%{c}$)\;{ }%}/{f}/s f

Below is a slightly unpacked version of the above GolfScript with explanation.  Since I don't think it could beat the APL or some other answers, I didn't bother to truly minify it.  I think that with inlining variable declarations, eliminating unnecessary variables, and other such tricks, this code could achieve approximately 190 characters without really changing the algorithm.  I think about about 10-15 characters could be removed if I better sorted out the conversion between arrays of ASCII values and strings.
#g is a function that returns the ASCII value of a random character or space.
#The ASCII values for capital letters are 65-90, and 32 is space.
{91,{64>},32+''+27rand=}:g;

#s is the string of interest.
'METHINKS IT IS LIKE A WEASEL':s;

#c is a function that returns the 'score' of a given string
#(the number of correct characters in the correct place).
{`{\.@\=s@==}+s,,\%{+}*}:c;

#t is a function that transforms a given string according to
#the specification (by replacing characters with a random character 5% of the times).
{{100rand 5>{ }{;g}if}%''+}:t;

#i is the initial random string.
[{g}]28*{~}%:i;

#Use '/' to unfold the initial value until the string is equal to the string of interest.
#Every loop, do the transformation 100 times, then sort by score c, and then take the top scoring string.
#Aggregate the results into an array a.
i{s=!}{{`100,\{\;t}+}~%{c}$)\;{ }%}/:a;

#Instantiate a counter variable k
0:k;

#f is the formatting function, that takes a string and formats it according to the spec.
{k):k\.': '@@c' -- score: '\++++n+}:f;

#Format every string in the array, and then format the string of interest
a{f}/
s f

JavaScript - 312
There is already a shorter JS solution above but it is using experimental pointer functions, so I thought I'd throw in another solution that is running in any JS environment:
for(r=Math.random,R=function(){return'METHINKS CODZAWFLBUGYQRXVJP'[~~(r()*27)]},_=[],_.$=n=0,D=function(s){for(c=[],c.$=i=0;i<28;){c[i]=s&&r()<.95?s[i]:R();_=(c.$+=c[i]=='METHINKS IT IS LIKE A WEASEL'[i++])>_.$?c:_};return c},D();_.$<28;){for(j=0;j++<1e2;)D(_);console.log(n+++': '+_.join('')+' -- score: '+_.$)}

Racket: 426 422 bytes
(let*((r random)(m map)(L" ABCDEFGHIJKLMONPQRSTUVWXYZ")(P(string->list"METHINKS IT IS LIKE A WEASEL"))(c(λ(l p)(m(λ(x)(if(<(r)p)(string-ref L(r 27))x))l)))(s(λ(l P p)(cons(foldl(λ(x y a)(if(eqv? x y)(+ a 1)a))0 l P)l))))(let r((g 0)(o (c P 1)))(let*((o(sort(m(λ(x)(s(c o 0.05)P 0))(range 100))(λ g(apply >(m car g)))))(p(caar o))(c(cdar o)))(printf"~a: ~a -- score: ~a
"g(list->string c)p)(if(= p 28)p(r(+ g 1)c)))))

Ungolfed:
(let* ((r random)
       (m map)
       (L " ABCDEFGHIJKLMONPQRSTUVWXYZ")
       (P (string->list "METHINKS IT IS LIKE A WEASEL"))
       (c (λ (l p)
            (m (λ (x)
                 (if (< (r) p)
                     (string-ref L (r 27))
                     x))
               l)))
       (s (λ (l P p)
            (cons (foldl (λ (x y a)
                           (if (eqv? x y)
                               (+ a 1)
                               a))
                         0
                         l
                         P)
                  l))))
  (let r ((g 0) (o (c P 1)))
    (let* ((o (sort (m (λ (x)
                         (s(c o 0.05)P 0))
                       (range 100))
                    (λ g
                      (apply >(m car g)))))
           (p (caar o))
           (c (cdar o)))
      (printf"~a: ~a -- score: ~a\n" g (list->string c) p)
      (if (= p 28)
          p
          (r (+ g 1) c)))))

 R, 291 characters
Longer than the previously proposed R answer but significantly different to be (I think) of interest:
a=sample;b=a(c<-c(LETTERS,' '),28,T);d=0;h=function(x)sum(x==strsplit("METHINKS IT IS LIKE A WEASEL",'')[[1]]);while(h(b)!=28){if(d){f=replicate(100,{e=runif(28)>.05;S=a(c,28,T);S[e]=b[e];S});g=f[,which.max(apply(f,2,h))];if(h(g)>h(b))b=g};cat(d,': ',b,' -- score: ',h(b),'\n',sep='');d=d+1}

With indentations:
a=sample
b=a(c<-c(LETTERS,' '),28,T)
d=0
h=function(x)sum(x==strsplit("METHINKS IT IS LIKE A WEASEL",'')[[1]])
while(h(b)!=28){
    if(d){
        f=replicate(100,{e=runif(28)>.05;S=a(c,28,T);S[e]=b[e];S})
        g=f[,which.max(apply(f,2,h))]
        if(h(g)>h(b))b=g
        }
    cat(d,': ',b,' -- score: ',h(b),'\n',sep='')
    d=d+1
    }

Outputs:
0: OUZ IT HNGNMSKIHSMCQUGXTOYVZ -- score: 1
1: OUZ IT HNGNMSKYHSMCQUGWXOYVZ -- score: 2
2: OUZ IT HNGNMSKYLSMCQUGWXOYVZ -- score: 3
3: OUZ IT HNGNMSKYLSMC UGWXOYVZ -- score: 4
...
68: METHINKS IT ES LIKE A WEASEL -- score: 27
69: METHINKS IT ES LIKE A WEASEL -- score: 27
70: METHINKS IT IS LIKE A WEASEL -- score: 28

The key here is the line f=replicate(100,{e=runif(28)>.05;S=a(c,28,T);S[e]=b[e];S}):
e=runif(28)>.05 draws randomly 28 numbers between 0 and 1 on a uniform distribution, and gives TRUE if over 5% and FALSE if under 5%. S=a(c,28,T) draws 28 new letters/spaces, while S[e]=b[e] replaces those for which the value was over 5% by the corresponding letter from the previous generation (i .e. those for which the value was less than 5% are therefore new).Then we replicate the operation 100 times.
On the following line (g=f[,which.max(apply(f,2,h))]) we compute the score for each of the 100 replicates and keep the one that has the maximum score (in case of equality the first one is kept) to be compared with the previous generation.

C 331
Another C solution that comes out to 331 characters. I think I might be able to improve it if I look a bit closer. Anyway the solution follows:
char l[29],b[29],*a="ABCDEFGHIJKLMNOPQRSTUVWXYZ ",i,j,*t="METHINKS IT IS LIKE A WEASEL",s,m=0;main(){for(i=0;i<28;i++)l[i]=a[rand()%27];while(strcpy(l,b))for(i=0;i<100;i++){for(j=s=0;j<28;j++){if(rand()%20==0)l[j]=a[rand()%27];if(l[j]==t[j])s++;}printf("%s -- score: %d\n",l,s);if(s>m){m=s;strcpy(b,l);}if(!strcmp(b,t))goto e;}e:;}

Haskell - 420 characters
This is more verbose than most; I'd put that down to my inexperience with randomness in haskell and proper use of monads.
import System.Random
r=randomRIO
z=zipWith
c=fmap((' ':['A'..'Z'])!!)$r(0,26)
y=(i.).replicate
i=mapM id
s=sum.z((fromEnum.).(==))"METHINKS IT IS LIKE A WEASEL"
u a n|n==0=c|True=return a
b n a|s n>s a=n|True=a
g=fmap(foldr1 b).y 100.mapM((r(0,20)>>=).u)
e x=do n<-g$x!!0;if(s$x!!0)==28 then return(n:x)else e(n:x)
main=y 28 c>>=(\a->e[a])>>=(i.z(\n x->putStrLn$shows n$": "++x++" -- score: "++(show$s x))[0..]).reverse

Javascript (411 389 376)
Shorter than some, longer than most.. [Methinks it will end.] EDIT: it wasn't ending due to an error. fixed it and ended up dropping the count too -- cool.
t='METHINKS IT IS LIKE A WEASEL';z=0;m=Math.random;r=function(){n=Math.floor(m()*27);return n?String.fromCharCode(64+n):' '};for(s='';s.length<28;s+=r());while(z<28){a=[s];while(a.length<100){x='';while(x.length<28){x+=m()>=.95?r():s.substr(x.length,1)}a.push(x)}for(i=0;i<100;i++){b=0;for(j=0;j<28;j++){b+=a[i][j]==t[j]?1:0;}if(b>z){alert(a[i]+' -- score: '+b);z=b;s=a[i]}}};

expanded:
t = 'METHINKS IT IS LIKE A WEASEL';
z = 0;
m = Math.random;
r = function(){
    n = Math.floor(m()*27);
    return n ? String.fromCharCode(64+n) : ' '
};
for(s='';s.length<28;s+=r());
while( z < 28 ){
    a = [s];
    while( a.length < 100 ){
        x = '';
        while( x.length < 28 ){
            x += m() >= .95 ? r() : s.substr(x.length, 1)
        }
        a.push(x)
    }
    for( i = 0; i < 100; i++ ){
        b = 0;
        for( j = 0; j < 28; j++ ){
            b += a[i][j] == t[j] ? 1 : 0;
        }
        if( b > z ){
            console.log( a[i] + ' -- score: ' + b);
            z = b;
            s = a[i]
        }
    }
};

[original:]
t='METHINKS IT IS LIKE A WEASEL';s='';z=0;m=Math.random;r=function(){n=Math.floor(m()*27);return n?String.fromCharCode(64+n):' '};c=function(){a=[s];while(a.length<100){x='';while(x.length<28){x+=m()>=.95?r():s.substr(x.length?x.length-1:0,1)}a.push(x)}for(i=0;i<100;i++){b=0;for(j=0;j<28;j++){b+=a[i][j]==t[j]?1:0;}if(b>z){alert(a[i]+' -- score: '+b);z=b;s=a[i]}i++}};while(s.length<28){s+=r()}while(z<28){c()}

Java: 557 534
enum W{W;public static void main(String[]a){char[]c=new char[28],h,d[];int i,k,e,s=W.s(c);for(i=0;i<28;i++)c[i]=W.r();for(i=0;;){W.p(i++,h=c,s);if(s>27)break;d=new char[100][28];for(char[]b:d){for(k=0;k<28;k++)b[k]=Math.random()<.05?W.r():h[k];if((e=W.s(b))>s){s=e;c=b;}}}}int s(char[]c){int s=0,k;for(k=0;k<28;k++)if(c[k]=="METHINKS IT IS LIKE A WEASEL".charAt(k))s++;return s;}void p(int i,char[]c,int s){System.out.println(i+": "+new String(c)+" -- score: "+s);}char r(){int i=(int)(Math.random()*27);return(char)(i==26?32:i+65);}}

Unwrapped:
enum W {
    W;

    public static void main(String[] a) {
        char[] c = new char[28], h, d[];

        int i, k, e, s = W.s(c);

        for(i = 0; i < 28; i++)
            c[i] = W.r();

        for(i = 0;;) {
            W.p(i++, h = c, s);

            if(s > 27)
                break;

            d = new char[100][28];

            for(char[] b : d) {
                for(k = 0; k < 28; k++)
                    b[k] = Math.random() < .05 ? W.r() : h[k];

                if((e = W.s(b)) > s) {
                    s = e;
                    c = b;
                }
            }
        }
    }

    int s(char[] c) {
        int s = 0, k;
        for(k = 0; k < 28; k++)
            if(c[k] == "METHINKS IT IS LIKE A WEASEL".charAt(k))
                s++;

        return s;
    }

    void p(int i, char[] c, int s) {
        System.out.println(i + ": " + new String(c) + " -- score: " + s);
    }

    char r() {
        int i = (int)(Math.random() * 27);
        return (char)(i == 26 ? 32 : i + 65);
    }
}

Groovy: 314
def(r,o,g)=[new Random(),{(0..27).sum{x->"METHINKS IT IS LIKE A WEASEL"[x]==it[x]?1:0}},0]
def q={([' ']+('A'..'Z'))[r.nextInt(27)]}
def s=q()*28
for(;;){println"${g++}: $s -- score: ${o(s)}"
if(o(s)==28)break
s=([s]*100).collect{it.collect{5>r.nextInt(100)?q():it}.sum()}.groupBy{o(it)}.max{it.key}.value[0]}

Output:
0:                              -- score: 5
1:          B               S   -- score: 6
2:  E       B               S M -- score: 7
3:  E       B               S M -- score: 7
4:  E       BT      X       S M -- score: 8
...
68: METHINKS IT IS LIKE L WEASEL -- score: 27
69: METHINKS IT IS LIKE L WEASEL -- score: 27
70: METHINKS IT IS LIKE L WEASEL -- score: 27
71: METHINKS IT IS LIKE L WEASEL -- score: 27
72: METHINKS IT IS LIKE A WEASEL -- score: 28

I feel like this is cheating so I'm not counting it as my 'real' answer; but I can save a few chars by passing "METHINKS IT IS LIKE A WEASEL" and " -- score: " as arguments to my script. Although technically it is 'externalizing strings'... which everyone knows is good practice :).
Groovy: 290
def(r,o,g)=[new Random(),{(0..27).sum{x->args[0][x]==it[x]?1:0}},0]
def q={([' ']+('A'..'Z'))[r.nextInt(27)]}
def s=q()*28
for(;;){println"${g++}: $s${args[1]}${o(s)}"
if(o(s)==28)break
s=([s]*100).collect{it.collect{5>r.nextInt(100)?q():it}.sum()}.groupBy{o(it)}.max{it.key}.value[0]}

Run like groovy script.groovy "METHINKS IT IS LIKE A WEASEL" " -- score: "

Golfscript (168 167)
:x;0['METHINKS IT IS LIKE A WEASEL'{}/]:o{;{27rand.!96*+64^}:r~}%{o=!}{100,{;.{20rand{}{;r}if}%}%{{[o\]zip{~=},,}:s~}$)@;\;x 2$+': '+1$+' -- score: '+1$s+n+:x;\)\}/;;x

Sadly, I can't seem to compress it quite to APL's level, but it's afaict currently a shared second place.
This is what it does;
# Grab the empty parameter string as initially empty output string.
:x;
# Start count at row #0
0
# Store the target string as an array in 'o'
['METHINKS IT IS LIKE A WEASEL'{}/]:o
# Create a random starting string, and define 'r' as a function generating a random char.
{;{27rand.!96*+64^}:r~}%
# Unfold as long as the latest string is different from the target string.
{o=!}
{
  // Generate 100 strings, sort by score and keep the highest.
  100,{;.{20rand{}{;r}if}%}%{{[o\]zip{~=},,}:s~}$)@;\;
  // Append the row to the output string, and increase the row number
  x 2$+': '+1$+' -- score: '+1$s+n+:x;\)\
}/
// Clean some junk on the stack
;;
// Output string
x

Python 2.7 - 319 bytes
Sure it's not the smallest, but it was fun to program.
from random import*
a=map(chr,range(65,91))+[' ']
c,i,y=choice,0,{}
s=[c(a)for i in[0]*28]
while 1:
 for j in[0]*100:v=[c(a)if .05>random()else x for x in s];y[sum(1if'METHINKS IT IS LIKE A WEASEL'[k]==v[k]else 0for k in range(28))]=v
 v=max(y.keys());s=y[v];print"%d: %s -- score: %d"%(i,''.join(y[v]),v);i+=1
 if v==28:break

Uses a recursing function, so it may reach the maximum recursion depth if there is some kind of weird devolution with the string.
ubuntu@ubuntu-OptiPlex-980:~$ python weasel.py
0: VPBHBSPWFTOG HAXSESCDNFPKWYE -- score: 1
1: VABHBSPWFTOG HAXSESCDNWPKWYE -- score: 2
2: VAWHBSPWFTOGIHAXSESSDNWPKWYE -- score: 3
3: VAWHBSPWFTOGIHAXSEFSGNWPKWYL -- score: 4
4: XAWHBSPYFTOGIHAXSEFSGNWPKWYL -- score: 4
5: XAWHBSKYFTOGIHAXSEFSGNWPKWYL -- score: 5
6: XAWHBSKYFTOGIHAXSEF GNWPKWYL -- score: 6
7: XAWHBSKYFTOGIHALSEF ANWPKWYL -- score: 8
8: XAKHBSKYFTTGIHALSEY ANWPKWYL -- score: 9
9: XAKHISKYFTTGIHALSEE ANWPKWYL -- score: 11
10: XAKHISKSFTTGIHALSEE ANWPKWYL -- score: 12
11: XAKHISKSFTTGIHALSBE ANWPKWKL -- score: 12
12: XAQHISKSFRT IHALSBE ANWPKWKL -- score: 13
13: XAQHISKSFIT IHALSBE ANWPKWKL -- score: 14
14: XAQHISKSFIT IHALSBE ANWPKWKL -- score: 14
15: XAQHISKSFIT IHALSBE ANWPKWKL -- score: 14
16: XALHISKSFIT ISALSBE ANWPKWKL -- score: 15
17: JALHISKSFIT ISALSBE ANWPAWKL -- score: 16
18: JALHISKSFIT ISALIBE ANWPAWKL -- score: 17
19: JALHISKSFIT ISALIBE ANWPAWKL -- score: 17
20: JALHISKSFIT ISALIBE ANWPAWKL -- score: 17
21: JALHISKSFIT ISALIKE ANWPAWYL -- score: 18
22: JALHISKSFIT IS LIKE ANWPAWYL -- score: 19
23: JALHISKSFIT IS LIKE ANWEAWYL -- score: 20
24: JALHISKSFIT IS LIKE ANWEAWYL -- score: 20
25: JALHISKSFIT IS LIKE ANWEAWZL -- score: 20
26: JALHISKS IT IS LIKE ANWEAAZL -- score: 21
27: JACHISKS IT IS LIKE ANWEASZL -- score: 22
28: JACHISKS IT IS LIKE ANWEASZL -- score: 22
29: MACHISKS IT IS LIKE ANWEASZL -- score: 23
30: MACHISKS IT IS LIKE ANWEASZL -- score: 23
31: MACHISKS IT IS LIKE AUWEASZL -- score: 23
32: MACHISKS IT IS LIKE AUWEASZL -- score: 23
33: MACHISKS IT IS LIKE AJWEASZL -- score: 23
34: MACHISKS IT IS LIKE A WEASZL -- score: 24
35: MACHISKS IT IS LIKE A WEASZL -- score: 24
36: MACHINKS IT IS LIKE A WEASZL -- score: 25
37: MACHINKS IT IS LIKE A WEASZL -- score: 25
38: MACHINKS IT IS LIKE A WEASZL -- score: 25
39: MBCHINKS IT IS LIKE A WEASZL -- score: 25
40: MBCHINKS IT IS LIKE A WEASZL -- score: 25
41: MBCHINKS IT IS LIKE A WEASZL -- score: 25
42: MBCHINKS IT IS LIKE A WEASZL -- score: 25
43: MBCHINKS IT IS LIKE A WEASZL -- score: 25
44: MBCHINKS IT IS LIKE A WEASZL -- score: 25
45: MECHINKS IT IS LIKE A WEASCL -- score: 26
46: MECHINKS IT IS LIKE A WEASCL -- score: 26
47: MECHINKS IT IS LIKE A WEASCL -- score: 26
48: MECHINKS IT IS LIKE A WEASCL -- score: 26
49: MECHINKS IT IS LIKE A WEASCL -- score: 26
50: MECHINKS IT IS LIKE A WEASCL -- score: 26
51: MEQHINKS IT IS LIKE A WEASCL -- score: 26
52: MEQHINKS IT IS LIKE A WEASCL -- score: 26
53: MEQHINKS IT IS LIKE A WEASCL -- score: 26
54: MEQHINKS IT IS LIKE A WEASCL -- score: 26
55: MEQHINKS IT IS LIKE A WEASCL -- score: 26
56: MEQHINKS IT IS LIKE A WEASCL -- score: 26
57: METHINKS IT IS LIKE A WEASCL -- score: 27
58: METHINKS IT IS LIKE A WEASCL -- score: 27
59: METHINKS IT IS LIKE A WEASCL -- score: 27
60: METHINKS IT IS LIKE A WEASCL -- score: 27
61: METHINKS IT IS LIKE A WEASCL -- score: 27
62: METHINKS IT IS LIKE A WEASCL -- score: 27
63: METHINKS IT IS LIKE A WEASCL -- score: 27
64: METHINKS IT IS LIKE A WEASCL -- score: 27
65: METHINKS IT IS LIKE A WEASEL -- score: 28

Massive thanks to Sp3000 for golfing help.

C++ 668
Not really short, but the only one in c++. (:
#include "stdafx.h"
using namespace std;int _tmain(){srand(time(NULL));string z="METHINKS IT IS LIKE A WEASEL";string a(28,' ');for(int i=0;i<28;++i){a[i]='A'+(rand()%26);}while(1){vector<std::pair<int,string>>d;for(int i=0;i<100;++i){d.push_back(std::pair<int,string>(0,""));for(int j=0;j<28;++j){int b=rand()%100;if(b<6){if(b<2){d[i].second+=' ';}else{d[i].second+='A'+(rand()%26);}}else {d[i].second+=a[j];}}}for(int i=0;i<100;++i){for(int j=0;j<28;++j){if(d[i].second[j]==z[j]){d[i].first++;}}}int y=0;for(int i=0;i<100;++i){if(d[i].first==28){cout<<d[i].second<<" "<<d[i].first;exit(1);}else if(d[i].first>y){y=d[i].first;a=d[i].second;}}cout<<a<<" "<<y<<endl;}}

more readable version:
#include "stdafx.h"
#include <string>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <time.h>
using namespace std;

int _tmain()
{
  srand(time(NULL));
  string z = "METHINKS IT IS LIKE A WEASEL";
  string a(28, ' ');
  for (int i = 0; i < 28; ++i)
  {
    a[i] = 'A' + (rand() % 26);
  }
  while(1)
  {
    vector<std::pair<int, string >> d;
    for (int i = 0; i < 100; ++i)
    {
      d.push_back(std::pair<int, string>(0, ""));
      for (int j = 0; j < 28; ++j)
      {
        int b = rand() % 100;
        if (b < 6)
        {
          if (b < 2)
          {
            d[i].second += ' ';
          }
          else {
            d[i].second += 'A' + (rand() % 26);
          }
        }
        else {
          d[i].second += a[j];
        }
      }
    }
    for (int i = 0; i < 100; ++i)
    {
      for (int j = 0; j < 28; ++j)
      {
        if (d[i].second[j] == z[j])
        {
          d[i].first++;
        }
      }
    }
    int y = 0;
    for (int i = 0; i < 100; ++i)
    {
      if (d[i].first == 28)
      {
        cout << d[i].second << " " << d[i].first;
        exit(1);
      }
      else if (d[i].first > y)
      {
        y = d[i].first;
        a = d[i].second;
      }
    }
    cout << a << " " << y << endl;
  }
}

Output:
VEBVTEWX CEWMYLTAJTYPFYYXBDQ 2
 EBVTEWX CEWMYLTAJT PFYYXBDQ 3
 EBVTEKX CEWMYLTAJT PFYYXBDQ 4
 EBVTEKX CEWM  TAJT PFYYXBDQ 5
 EBVTEKX CE M  TAJT P YYX DQ 7
MEPVTEKX CE M  TAJT P YY  D  8
MEPVT KX CE M  TAJT A YY  D  9
MEPVI KX CE M  UAJT A YY  D  10
MEPSI KX CE M  UAJT A YY  D  10
MEPSI K  CE M  UAJE A YY  DE 11
MEPSI K  CE M  UAJE A YY  DL 12
MEPPI K  CE I  UDJE A YY  DL 13
MEPRI K  CE IS UDJE A YY  DL 14
MEPRI K  CE IS UDJE A  Y  DL 14
MEPHI K  CE IS UDJE A  Y  DL 15
MEPHI K  CE IS UDJE A  Y  DL 15
MEPHI K  CE IS RDBE A  E  DL 16
MEPHIQK  CE IS RD E A  E  DL 16
MEPHIQK  CE IS RD E A  E  DL 16
ME HIQK  CE IS RDXE A  E  DL 16
ME HIQK  CE IS W XE A  E  DL 16
ME HIQK  CE IS W XE A  E  EL 17
ME HIQK  CE IS W XE A  E  EL 17
ME HIQK  CE IS   XE A  E  EL 17
MEGHIQK  CE IS   XE A WEO EL 18
MEGHIQK  CE IS   XE A WEO EL 18
MEGHIQK  CE IS   XE A WEO EL 18
MEGHIQK  CE IS   XE A WE  EL 18
MEGHIQK  CE IS   XE A WE SEL 19
MEGHIQK  CE IS L XE A WE SEL 20
MEGHINK  CE IS L XE A WE SEL 21
MEGHINK  CE IS L XE A WE SEL 21
MEGHINK  CN IS L XE A WEASEL 22
MEGHINK   H IS L XE A WEASEL 22
MEGHINK   H IS L XE A WEASEL 22
METHINK   H IS L XE A WEASEL 23
METHINK   H IS L XE A WEASEL 23
METHINK   H IS L XE A WEASEL 23
METHINK   H IS L XE A WEASEL 23
METHINK   H IS L XE A WEASEL 23
METHINK   H IS L XE A WEASEL 23
METHINK  ZH IS L XE A WEASEL 23
METHINK  ZH IS LIXE A WEASEL 24
METHINK  ZH IS LIKE A WEASEL 25
METHINKD ZH IS LIKE A WEASEL 25
METHINKD ZH IS LIKE A WEASEL 25
METHINKD ZH IS LIKE A WEASEL 25
METHINKD ZH IS LIKE A WEASEL 25
METHINKD ZT IS LIKE A WEASEL 26
METHINKD ZT IS LIKE A WEASEL 26
METHINKD ZT IS LIKE A WEASEL 26
METHINKS ZT IS LIKE A WEASEL 27
METHINKS IT IS LIKE A WEASEL 28

Julia, 281 bytes
Golfed:
r=n->['A':'Z',' '][rand(1:27,n)]
s=a->sum(a.=="METHINKS IT IS LIKE A WEASEL".data)
p=(z,a,s)->println(z,": ",join(a)," -- score: ",s)
a = r(28)
b = s(a)
z = 0
p(z,a,b)
while b<28
c=b
d=a
for i=1:100
e=[rand()<.95?i:r(1)[1]for i=a]
f=s(e)
if(f>c)
c=f
d=e
end
end
a=d
b=c
p(z,a,b)
z+=1
end

The algorithm itself isn't very clever, but there are some cool bits in here.  Combining a character range with another character, then indexing into it: ['A':'Z',' '][rand(1:27,n)] and taking the sum of an array of booleans (common, but I still love the idea): sum(a.=="METHINKS IT IS LIKE A WEASEL".data).  Glad I got under 300!
Ungolfed:
randchar = n -> ['A':'Z',' '][rand(1:27,n)]
score = a -> sum(a.=="METHINKS IT IS LIKE A WEASEL".data)
myprint = (z,a,s) -> println(z,": ",join(a)," -- score: ",s)
currentarray = randchar(28)
currentscore = score(currentarray)
z = 0
myprint(z,currentarray,currentscore)
while currentscore < 28
    bestscore = currentscore
    bestarray = currentarray
    for i = 1:100
        temparray = [rand()<.95?i:randchar(1)[1]for i=currentarray]
        tempscore = score(temparray)
        if(tempscore > bestscore)
            bestscore = tempscore
            bestarray = temparray
        end
    end
    currentarray = bestarray
    currentscore = bestscore
    myprint(z,currentarray,currentscore)
    z+=1
end

Japt, 98 bytes
;ªBiS ö28
=#dÆ£20ö ?X:BiS)öÃÃñL=_¬xÈ¶Yg`Ú0ks   ¦ke a Øâel`u
mL o
=o
Op[T°+':X'-²`sÖ`W]¸
W<28©ß

Not a winner, but I really wanted to answer this fun challenge.
Test it

JavaScript (Node.js), 328 bytes
t="METHINKS IT IS LIKE A WEASEL";z=0;m=Math.random;r=_=>(n=0|27*m())?String.fromCharCode(64+n):" ";for(s="";28>s[l="length"];s+=r())for(;28>z;){for(a=[s];100>a[l];){for(x="";28>x[l];)x+=.95<=m()?r():s.substr(x[l],1);a.push(x)}for(i=0;100>i;i++){for(j=b=0;28>j;j++)b+=a[i][j]==t[j];b>z&&(alert(a[i]+" -- score: "+b),z=b,s=a[i])}}

Try it online!
This is rather long and can be shortened, just haven't gotten around to that.

Explanation :
This is not exactly an explanation but it is better indented and can

t = "METHINKS IT IS LIKE A WEASEL";
z = 0;
m = Math.random;
r = _ => (n = 0 | 27 * m()) ? String.fromCharCode(64 + n) : " ";
for (s = ""; 28 > s[l = "length"]; s += r())
 for (; 28 > z;) {
  for (a = [s]; 100 > a[l];) {
   for (x = ""; 28 > x[l];) x += .95 <= m() ? r() : s.substr(x[l], 1);
   a.push(x)
  }
  for (i = 0; 100 > i; i++) {
   for (j = b = 0; 28 > j; j++) b += a[i][j] == t[j];
   b > z && (alert(a[i] + " -- score: " + b), z = b, s = a[i])
  }
 }

Pyth, 116 bytes
Ls.bqNY"METHINKS IT IS LIKE A WEASEL"bj.e%"%d: %s -- score: %s"[ksbyb).W<yeH28+Z]eoyNmmO.[O+r1G\ k20eZ100]mO+r1G\ 28

Try it online.
Ls.bqNY"..."bj.e%"..."[ksbyb).W<yeH28+Z]eoyNmmO.[O+r1G\ k20eZ100]mO+r1G\ 28

L                                                                             Define fitness function, y(b):
       "..."                                                                    The target string
  .b        b                                                                   Map over characters of the above and b:
    qNY                                                                           Are they equal? True = 1, False = 0
 s                                                                              Take the sum
                                                                    r1G       The uppercase alphabet
                                                                   +   \      Append a space
                                                                  O           Choose one at random
                                                                ]m       28   Create an array of 28 of the above, wrap in array
                             .W                                               Functional while, with above as initial value
                                                                                Continue condition (current value = H):
                                 eH                                               Last value of H
                                y                                                 Apply fitness function to the above
                               <   28                                             Check the above is less than 28
                                                                                Function body (current value = Z)
                                             m             eZ                     Map each character (as k) in the last value in Z over:
                                                 O+r1G\                             Choose random char/space (as above)
                                               .[       k20                         Pad the above to length 20 using k
                                              O                                     Choose one of the above at random
                                            m                100                  Do the above 100 times
                                         oyN                                      Order the above by the fitness function
                                       ]e                                         Take the last of the above, wrap in array
                                     +Z                                           Append to Z
                                                                              Return value of while is array of all steps taken
              .e                                                              Map each entry with its index over:
                       k                                                        Current index
                        sb                                                      Current entry joined on empty string
                          yb                                                    Fitness of current entry
                      [     )                                                   Wrap the above 3 results in an array
                %"..."                                                          String formatting using the output string
             j                                                                Join on newlines, implicit output


text:
printf-style string formatting
Challenge
Write a function that implements C printf-style string formatting.
Rules

You must implement at least %%, %c, %s, %d and %f.
You must not use a built-in string formatting method.
You must not run external programs or connect to the Internet from your program.
It's up to you to decide how to handle invalid input, but your program must not terminate abnormally.
You should write a variadic function if possible.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

What does %c do? Pretty sure %s, %d and %f are for strings, ints and floats respectivelly, but unsure about %c.

%c displays the ASCII value of a passed-in int IIRC

It prints the character, so 97 and 'a' would both become a on the output.

no need to support some form like %-02d right? just that three %c, %s, %d?

@YOU Correct. That's enough.

I presume that it's necessary to handle %% too? What about unsupported %<char>: should that give an error, treat it as a literal %, or is the choice up to the implementer?

@PeterTaylor Thanks, I've clarified the instructions.

No build in language feature? What about using the build in if "feature"?

@JohannesKuhn Thanks for noticing, I'll clarify that, as I'm already on clarifying the question.

APL (73)
{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺}

Some tests:
      'a:%c b:%s c:%d'{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺} 65 'foo' 67
a:A b:foo c:67

      printf←{⊃,/,⌿↑(⊂2∘↓¨Z⊂G),⊂{'c'0≡⍵,∊⊃⍺:⎕UCS⍺⋄⍕⍺}/⍵,⍪⌷∘G¨1↓1+(Z←G='%')/⍳⍴G←'%!',⍺}
      '1:%s 2:%s 3:%d 4:%c 5:%c' printf 'foo' 'bar' 100 110 'z'
1:foo 2:bar 3:100 4:n 5:z
      'The %s brown %c%c%c jumps over the %s dog.' printf 'quick' 102 111 'x' 'lazy'
The quick brown fox jumps over the lazy dog.

Explanation:

G←'%!',⍺: prefix a dummy specifier to the string (for easier processing)
(Z←G='%')/⍳⍴G: find the indices of all the % characters in the string; also store a bitmask in Z
⌷∘G¨1↓1+: select all the characters next to the %s, and drop the dummy.
⍵,⍪: match up each specifier with its value from the right argument.
{...}/: run the following function on each pair:

'c'0≡⍵,∊⊃⍺: if the argument is a number and the specifier is c:
:⎕UCS⍺: then return the unicode value of the argument,
⋄⍕⍺: otherwise, return the string representation of the argument.

⊂: enclose
⊂2∘↓¨Z⊂G: split the string on the %s and then remove the first two characters of each substring (this is where the dummy comes in), and enclose the result of that.
↑: make a matrix out of the two enclosed arrays, matching up each substring with the value that should follow it.
,⌿: join each substring with its value.
⊃,/: then join the resulting strings.

It's always fun to see esoteric languages that look like gibberish. ;)

@nyuszika7h: This is actually a serious language. It dates from the 1960s and it is still in use. It would look a bit less like gibberish if it wasn't golfed.

I see, interesting.

@nyuszika7h: Well, technically it's list oriented programming language, so you could say it's designed for code golf, especially considering it uses a special character set intended to make programs more readable, and less verbose. And it was an inspiration for J programming language and GolfScript.

@xfix I thought LISP was the list oriented programming language?  We used APL in university for real work - being able to handle arrays natively is really handy.  J was designed by one of the inventers of APL as its "successor"  - of course that doesn't mean that it isn't useful for code golf...

Lua 5.2, 115 bytes
-- Function definition, 115 chars
function f(f,...)n,t=0,{...}return(f:gsub('%%(%a)',function(s)n=n+1return(({c=s.char})[s]or tostring)(t[n])end))end

-- Usage example
print(f('Happy %cew %d %s %f',78,2014,'Year!',math.pi))
-- Output: Happy New 2014 Year! 3.1415926535898

Nice one. Which version of Lua? 5.1.5 gives “malformed number near '1return'”. Small problem with “%c”, it fails on 'N' instead of 78. Or is it also just my old Lua's peculiarity?

@manatwork - Try here

Yepp, works there.

Works for me on Lua 5.2.3.

Ruby: 102 characters
f=->s,*a{s.gsub(/%(.)/){$1==?%??%:a.shift.send({?c=>:chr,?s=>:to_s,?d=>:to_i,?f=>:to_f}[$1])rescue$&}}

Sample run:
irb(main):001:0> f=->s,*a{s.gsub(/%(.)/){$1==?%??%:a.shift.send({?c=>:chr,?s=>:to_s,?d=>:to_i,?f=>:to_f}[$1])rescue$&}}
=> #<Proc:0x96634ac@(irb):1 (lambda)>

irb(main):002:0> puts f["percent : %%\n   char : %c or %c\n string : %s or %s or %s\ndecimal : %d or %d or %d\n  float : %f or %f or %f\ninvalid : %x or %s or %d or %f", 65, 'B', 'format me', 42, Math::PI, 42, Math::PI, '2014', 42, Math::PI, '2014', 'more']
percent : %
   char : A or B
 string : format me or 42 or 3.141592653589793
decimal : 42 or 3 or 2014
  float : 42.0 or 3.141592653589793 or 2014.0
invalid : %x or  or 0 or 0.0
=> nil

Invalid format specifiers are kept in place. Format specifiers without argument value are replaced with the empty value of the given type.

You can supply an anonymous function, so drop the leading f

Indeed. But as I remember, at the time of posting this, anonymous functions were not unanimously accepted. As for now neither the Lua answer was updated to anonymous function (to save the same amount of characters), I think I will not start the update campaign.

C++ (281 characters)
#include<sstream>
#include<cstdarg>
#define q(x)va_arg(v,x);break;case
std::string p(char*f,...){std::ostringstream r;va_list v;va_start(v,f);while(*f)if(*f=='%')switch(++f,*f++){case's':r<<q(char*)'d':r<<q(int)'c':r<<(char)q(int)'%':r<<'%';}else r<<*f++;va_end(v);return r.str();}

I hate C++, but it seemed like a good choice (I really would go with C, if not that char* pointer requires too much effort to be actually useful). Takes char* arguments, and std::string result, but hey, that's C++, so who cares about consistency (in language that itself isn't consistent)?

This doesn't compile, as it doesn't have a main function.

@nyuszika7h: The question was about making a function, not main. But if you need sample main, try https://gist.github.com/xfix/8238576 (I used that one while testing this function).

True, you can't really make a meaningful main function, adding one would just increase the character count. If I didn't want to modify the code, I could add an accompanying header file and #include it from my test program.

Java, 201 186 174 bytes
12 bytes thanks to Kevin Cruijssen
String f(String s,Object...a){String r="";for(char c,i=0,j=0;i<s.length();r+=c==37?(c=s.charAt(i++))<38?c:c==99?(char)(int)a[j++]:a[j++]:c==37?"":c)c=s.charAt(i++);return r;}

Try it online!

I'm not entirely sure, but I think you can remove =s.charAt(0) from char c=s.charAt(0). It still works in the TIO when I do so.

@KevinCruijssen I swear that's quite clever.

I know it's been a while, but you can save 8 more bytes by printing directly: void f(String s,Object...a){for(char c,i=0,j=0;i<s.length();System.out.print(c==37?(c=s.charAt(i++))<38?c:c==99?(char)(int)a[j++]:a[j++]:c==37?"":c))c=s.charAt(i++);} 166 bytes (and some more by converting to Java 8, but that's not really your thing, is it?)

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes