On August 26th last month, Denyse O’Leary posted a contest here at UD asking for the original WEASEL program(s) that Richard Dawkins was using back in the late 1980s to show how Darwinian evolution works. Although Denyse’s post generated 377 comments (thus far), none of the entries could reasonably be thought to be Dawkins’s originals.
It seems that Dawkins used two programs, one in his book THE BLIND WATCHMAKER, and one for a video that he did for the BBC (here’s the video-run of the program; fast forward to 6:15). After much beating the bushes, we finally heard from someone named “Oxfordensis,” who provided the two PASCAL programs below, which we refer to as WEASEL1 (corresponding to Dawkins’s book) and WEASEL2 (corresponding to Dawkins’s BBC video). These are by far the best candidates we have received to date.
Unless Richard Dawkins and his associates can show conclusively that these are not the originals (either by providing originals in their possession that differ, or by demonstrating that these programs in some way fail to perform as required), we shall regard the contest as closed, offer Oxfordensis his/her prize, and henceforward treat the programs below as the originals.
For WEASEL1 and WEASEL2 click here:
WEASEL1:
Program Weasel;
Type
Text=String[28];
(* Define Parameters *)
Const
Alphabet:Text=’ABCDEFGHIJKLMNOPQRSTUVWXYZ ‘;
Target:Text=’METHINKS IT IS LIKE A WEASEL’;
Copies:Integer=100;
Function RandChar:Char;
(* Pick a character at random from the alphabet string *)
Begin
RandChar:=Alphabet[Random(27)+1];
End;
Function SameLetters(New:Text; Current:Text):Integer;
(* Count the number of letters that are the same *)
Var
I:Integer;
L:Integer;
Begin
L:=0;
I:=0;
While I< =Length(New) do Begin If New[I]=Current[I] Then L:=L+1; I:=I+1; End; SameLetters:=L; End; Var Parent:Text; Child:Text; Best_Child:Text; I:Integer; Best:Integer; Generation:Integer; Begin Randomize; (* Initialize the Random Number Generator *) (* Create a Random Text String *) Parent:=''; For I:=1 to Length(Target) do Begin Parent:=Concat(Parent, RandChar) End; Writeln(Parent); (* Do the Generations *) Generation:=1; While SameLetters(Target, Parent) <> Length(Target)+1 do
Begin
(* Make Copies *)
Best:=0;
For I:=1 to Copies do
Begin
(* Each Copy Gets a Mutation *)
Child:=Parent;
Child[Random(Length(Child))+1]:=RandChar;
(* Is This the Best We’ve Found So Far? *)
If SameLetters(Child, Target) > Best Then
Begin
Best_Child:=Child;
Best:=SameLetters(Child, Target);
End;
End;
Parent:=Best_Child;
(* Inform the User of any Progress *)
Writeln(Generation, ‘ ‘, Parent);
Generation:=Generation+1;
End;
End.
WEASEL2:
PROGRAM WEASEL;
USES
CRT;(* RETURN A RANDOM LETTER *)
FUNCTION RANDOMLETTER : CHAR;
VAR
NUMBER : INTEGER;
BEGIN
NUMBER := RANDOM(27);
IF NUMBER = 0 THEN
RANDOMLETTER := ‘ ‘
ELSE
RANDOMLETTER := CHR( ORD(‘A’) + NUMBER – 1 );
END;(* MEASURE HOW SIMILAR TWO STRINGS ARE *)
FUNCTION SIMILARITY(A : STRING; B : STRING) : INTEGER;
VAR
IDX : INTEGER;
SIMCOUNT : INTEGER;
BEGIN
SIMCOUNT := 0;FOR IDX := 0 TO LENGTH(A) DO
BEGIN
IF A[IDX] = B[IDX] THEN
SIMCOUNT := SIMCOUNT + 1;
END;
SIMILARITY := SIMCOUNT;
END;FUNCTION RANDOMSTRING(LEN : INTEGER) : STRING;
VAR
I : INTEGER;
RT : STRING;
BEGIN
RT := ”;
FOR I := 1 TO LEN DO
BEGIN
RT := RT + RANDOMLETTER;
END;
RANDOMSTRING := RT;
END;VAR
X : INTEGER;
TARGET : STRING;
CURRENT : STRING;
OFFSPRING : STRING;
TRIES : LONGINT;
FOUND_AT : INTEGER;
BEGIN
RANDOMIZE;CLRSCR;
WRITELN(‘Type target phrase in capital letters’);
READLN(TARGET);
(* PUT SOME STRING ON THE SCREEN *)
TEXTCOLOR(GREEN);
GOTOXY(1, 6);
WRITELN(‘Target’);GOTOXY(10, 6);
WRITELN(TARGET);TEXTCOLOR(BLUE);
GOTOXY(1,13);
WRITELN(‘Darwin’);TEXTCOLOR(BLUE);
GOTOXY(1,19);
WRITELN(‘Random’);TEXTCOLOR(WHITE);
GOTOXY(1, 25);WRITE(‘Try number’);
(* PICK A RANDOM STRING TO START DARWIN SEARCH *)
CURRENT := RANDOMSTRING(LENGTH(TARGET));(* RUN THROUGH MANY TRIES *)
FOUND_AT := 0;
FOR TRIES := 1 TO 100000 DO
BEGIN(* Darwin *)
OFFSPRING := CURRENT;
OFFSPRING[ 1 + RANDOM(LENGTH(OFFSPRING)) ] := RANDOMLETTER;GOTOXY(10,13);
WRITELN(OFFSPRING, ‘ ‘);IF( SIMILARITY(OFFSPRING, TARGET) >= SIMILARITY(CURRENT, TARGET) ) THEN
CURRENT := OFFSPRING;IF( (SIMILARITY(CURRENT, TARGET) = LENGTH(TARGET)) AND (FOUND_AT = 0) ) THEN
BEGIN
(* TELL THE USER WHAT WE FOUND *)
FOUND_AT := TRIES;
GOTOXY(1, 15);
TEXTCOLOR(BLUE);
WRITELN(‘Darwin’);
TEXTCOLOR(WHITE);
GOTOXY(9, 15);
WRITELN(‘reached target after’);
GOTOXY(37, 15);
TEXTCOLOR(BLUE);
WRITELN(FOUND_AT);
WRITE(‘tries’);
TEXTCOLOR(WHITE);GOTOXY(1, 21);
TEXTCOLOR(BLUE);
WRITE(‘Random’);
TEXTCOLOR(WHITE);
WRITELN(‘ would need more than ‘);
TEXTCOLOR(BLUE);
WRITELN(‘1000000000000000000000000000000000000000’);
TEXTCOLOR(WHITE);
WRITE(‘tries’);
END;(* Random *)
GOTOXY(10, 19);
WRITELN(RANDOMSTRING(LENGTH(TARGET)), ‘ ‘);GOTOXY(27,25);
WRITE(TRIES, ‘ ‘);
END;GOTOXY(1, 20);
End.