#include // Needed for rand(), which gives a random starting genome and picks a random site for mutation.
#include // Provides a random seed value for the rand() function
#define GENOMESIZE 16
#define GUARDPAGE GENOMESIZE
void bigBang(); //Initializes, randomizes, and documents via printing to standard output.
int getFitness(); //Defined here as the number of elements matching their respective neighbors.
void copyGenome(char *from, char *to); //Copies the pattern from one chunk of RAM to another.
void pointMutate(); //Switches one element, chosen at random.
char *describe(); //Gives directions for writing the genome down. The first digit is the first bit of the genome.
//The remaining items tell how many of the same bits follow before you should change from
//ones to zeros, or vice versa.
void crunch(); //Prints the final genome with description and blithely ignores potential errors before exit.
int main (int argc, const char * argv[]) {
int i, oldFitness, newFitness;
char genome[GENOMESIZE + 1]; // Stores a pattern of '0' and '1' values. Initially random, but updated with improved patterns
// from "newGenome".
char newGenome[GENOMESIZE + 1]; //Holds a copy of the genome for mutation and testing.
char description[2 * GENOMESIZE + 2 + GUARDPAGE]; //Call me paranoid, or call me if you can prove GUARDPAGE redundant.
//Holds the starting byte, then the lengths of runs of similar bytes,
//separated by commas.
bigBang(genome, newGenome, description); //Puts zero delimiters on the arrays, and initializes a random genome.
//The random improvement process:
//A trial copy is made, and stored in "newGenome". "newGenome" gets mutated, and if the new fitness is better than the
//old fitness, the original genome is substituted for the old.
for (i = 0; i < 1000; i++){
oldFitness = getFitness(genome);
copyGenome(genome, newGenome);
pointMutate(newGenome);
newFitness = getFitness(newGenome);
if (newFitness > oldFitness) {
copyGenome(newGenome, genome);
}
}
// This process uses only two genome carriers, versus the 10^22 or so living things on Earth.
// One big difference between this process and biological evolution is that the
//definition of "fitness" is explicit, unchanging, and determined by you, the programmer.
//Thus, it is closer to the concept of "efficiency." The word "Fitness" emphasises
//the environment to which the genome must "fit".
// Extinction is meted out in a summary, binary fashion. This disallows "transitional"
//patterns, which, though less "fit" than their parent, are nearer to an even better pattern.
//Consequently, you will see that the ideal patterns of "000..." and "111..." are seldom found,
//even with infinitely many mutations. This corresponds more to breeding than to wild
//or family-based reproduction.
// Translocation, that is, the occasional addition, removal, reversal, or transfer of whole chunks
//from one genome to another, is not available. Neither is chromosome shuffling via meiosis and fusion.
crunch(genome, description);
return 0;
}
char * describe(char object[], char description[]){
int descriptionCursor, runLength, i;
descriptionCursor = runLength = i = 0;
descriptionCursor += sprintf(description , "%d", object[0] - '0');
object[GENOMESIZE] = object[0]; // Replace the null terminator with a copy of the first byte (Dangerous*).
for (i = 0; i < GENOMESIZE; i++, runLength++){
if (object[i] != object[i+1]) {
descriptionCursor += sprintf(description + descriptionCursor, ",%d", runLength);
runLength = 0;
}
}
object[GENOMESIZE] = 0; // (*End danger) Repaired the object so it will be a safe c string again.
return description;
}
void copyGenome(char from[], char to[]){
int i;
for (i = 0; i < GENOMESIZE; i++) to[i] = from [i];
}
void bigBang(char g[], char n[], char d[]){
int i;
time_t t;
t = time(&t);
srand((unsigned int)t);
for(i = 0; i < GENOMESIZE; i++){
g[i] = '0' + (char)(rand() & 1);
}
g[GENOMESIZE] = 0;
n[GENOMESIZE] = 0;
d[GENOMESIZE + 1] = 0;
printf("bigBang: %s: Description: %s\n", g, describe(g, d) );
}
void crunch(char g[], char d[]){
printf("crunch: %s: Description: %s\n", g, describe(g, d) );
}
int getFitness(char *digits){
int i, Fitness = 0;
for(i = 0; i < GENOMESIZE; i++){
if( digits[i] == digits[ (i+GENOMESIZE-1) % GENOMESIZE ] ){
Fitness++ ;
}
}
return Fitness;
}
void pointMutate(char dna[]){
int site = (int)(rand() % GENOMESIZE);
dna[site] = (dna[site] == '0') ? '1': '0';
}