Starting with:

 The target string: "METHINKS IT IS LIKE A WEASEL".
 An array of random characters chosen from the set of upper-case letters together with the space, and of the same length as the target string. (Call it the parent).
 A fitness function that computes the ‘closeness’ of its argument to the target string.
 A mutate function that given a string and a mutation rate returns a copy of the string, with some characters probably mutated.
 While the parent is not yet the target:
 copy the parent C times, each time allowing some random probability that another character might be substituted using mutate.
 Assess the fitness of the parent and all the copies to the target and make the most fit string the new parent, discarding the others.
 repeat until the parent converges, (hopefully), to the target.


See also

   Wikipedia entry:   Weasel algorithm.
   Wikipedia entry:   Evolutionary algorithm.

Note: to aid comparison, try and ensure the variables and functions mentioned in the task description appear in solutions



A cursory examination of a few of the solutions reveals that the instructions have not been followed rigorously in some solutions. Specifically,

 While the parent is not yet the target:
 copy the parent C times, each time allowing some random probability that another character might be substituted using mutate.
Note that some of the the solutions given retain characters in the mutated string that are correct in the target string. However, the instruction above does not state to retain any of the characters while performing the mutation. Although some may believe to do so is implied from the use of "converges"

(:* repeat until the parent converges, (hopefully), to the target.

Strictly speaking, the new parent should be selected from the new pool of mutations, and then the new parent used to generate the next set of mutations with parent characters getting retained only by not being mutated. It then becomes possible that the new set of mutations has no member that is fitter than the parent!

As illustration of this error, the code for 8th has the following remark.

Create a new string based on the TOS, changing randomly any characters which
don't already match the target:

NOTE: this has been changed, the 8th version is completely random now

Clearly, this algo will be applying the mutation function only to the parent characters that don't match to the target characters!

To ensure that the new parent is never less fit than the prior parent, both the parent and all of the latest mutations are subjected to the fitness test to select the next parent.




 
 !***************************************************************************************************
 	module evolve_routines
 !***************************************************************************************************
 	implicit none
 
 	!the target string:
 	character(len=*),parameter :: targ = 'METHINKS IT IS LIKE A WEASEL'
 
 	contains
 !***************************************************************************************************
 
 !********************************************************************
 	pure elemental function fitness(member) result(n)
 !********************************************************************
 ! The fitness function.  The lower the value, the better the match.
 ! It is zero if they are identical.
 !********************************************************************
 
 	implicit none
 	integer :: n
 	character(len=*),intent(in) :: member
 
 	integer :: i
 
 	n=0
 	do i=1,len(targ)
 		n = n + abs( ichar(targ(i:i)) - ichar(member(i:i))  )
 	end do
 
 !********************************************************************
 	end function fitness
 !********************************************************************
 
 !********************************************************************
 	pure elemental subroutine mutate(member,factor)
 !********************************************************************
 ! mutate a member of the population.
 !********************************************************************
 
 	implicit none
 	character(len=*),intent(inout) :: member   !population member
 	real,intent(in) :: factor                  !mutation factor
 
 	integer,parameter :: n_chars = 27	!number of characters in set
 	character(len=n_chars),parameter :: chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '
 
 	real    :: rnd_val
 	integer :: i,j,n
 
 	n = len(member)
 
 	do i=1,n
 		rnd_val = rand()
 		if (rnd_val<=factor) then   !mutate this element			
 			rnd_val = rand()
 			j = int(rnd_val*n_chars)+1   !an integer between 1 and n_chars
 			member(i:i) = chars(j:j)
 		end if
 	end do
 
 !********************************************************************
	end subroutine mutate
 !********************************************************************
 
 !***************************************************************************************************
 	end module evolve_routines
 !***************************************************************************************************
 
 !***************************************************************************************************
 	program evolve
 !***************************************************************************************************
 ! The main program
 !***************************************************************************************************
 	use evolve_routines
 
 	implicit none
 
 	!Tuning parameters:
 	integer,parameter :: seed = 12345             !random number generator seed
 	integer,parameter :: max_iter = 10000         !maximum number of iterations
 	integer,parameter :: population_size = 200    !size of the population
 	real,parameter    :: factor = 0.04            ![0,1] mutation factor
 	integer,parameter :: iprint = 5               !print every iprint iterations
 
 	!local variables:
 	integer :: i,iter
 	integer,dimension(1) :: i_best
 	character(len=len(targ)),dimension(population_size) :: population
 
 	!initialize random number generator:
 	call srand(seed)
 
 	!create initial population:
 	! [the first element of the population will hold the best member]
 	population(1) = 'PACQXJB CQPWEYKSVDCIOUPKUOJY'  !initial guess
 	iter=0
 
 	write(*,'(A10,A30,A10)') 'iter','best','fitness'
 	write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
 
 	do 
 
 		iter = iter + 1 !iteration counter
 
  		!write the iteration:
 		if (mod(iter,iprint)==0) write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
 
 		!check exit conditions:
 		if ( iter>max_iter .or. fitness(population(1))==0 ) exit
 
 		!copy best member and mutate:
 		population = population(1)	
 		do i=2,population_size
 			call mutate(population(i),factor)	
 		end do
 
 		!select the new best population member:
 		! [the best has the lowest value]
 		i_best = minloc(fitness(population))
 		population(1) = population(i_best(1))
 
 	end do
 
 	!write the last iteration:
 	if (mod(iter,iprint)/=0) write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
 
 	if (iter>max_iter) then
 		write(*,*) 'No solution found.'
 	else
 		write(*,*) 'Solution found.'
 	end if
 
 !***************************************************************************************************
 	end program evolve
 !***************************************************************************************************
 