My First (Amateur) Evolutionary Algorithm

Generate a random string and mutate it until it "evolves" into the target string.

by pendensproditor

HTML

<form id="target_form">
    <p><b>Target Phrase</b>: <input id="target" type="text" value="there is grandeur in this view of life" /> <button>Run</button></p>
</form>

<p><b>Random Phrase</b>: <span id="ancestor"></span></p>

<p><b>Generations</b> (with degree of difference from target):</p>

<pre id="generations"></pre>

CSS

body {
    padding: 30px;
}

p {
    margin-bottom: 20px;
    font-family: Arial, Verdana, sans-serif;
    font-size: 14px;  
}

input {
    width: 300px;   
}

pre {
    padding-left: 40px;
    font-size: 11px;  
}

JavaScript

/*

Inspiration: http://www.electricmonk.nl/log/2011/09/28/evolutionary-algorithm-evolving-hello-world/

A string of gibberish is mutated by shifting a single letter left or right alphabetically -- in other words, a 'q' will be shifted to 'p' or 'r' randomly. The new phrase is then compared to the target phrase, and if the similarity has increased the mutation will be kept. The process is repeated until the phrases match.

*/

(function(doc) {
    
    "use strict";

    // let's skip non-letter characters and the hassle of ASCII values for now
    var allowedCharacters = 'abcdefghijklmnopqrstuvwxyz ',
        targetElem = doc.getElementById('target'),
        ancestorElem = doc.getElementById('ancestor'),
        generationsElem = doc.getElementById('generations'),
        targetStr, ancestorStr, ancestorScore;

    doc.getElementById('target_form').onsubmit = function() {
        runSimulation();
        return false;
    };

    function runSimulation() {
        targetStr = targetElem.value.toLowerCase();
        ancestorStr = generateRandomString(targetStr.length);
        ancestorScore = getStringScore(ancestorStr);

        ancestorElem.innerHTML = '&ldquo;' + ancestorStr + '&rdquo;';

        var generationsHTML = '',
            generation = 0;
        // give up after 20,000 generations to avoid a possible infinite loop
        while (ancestorScore > 0 && generation++ < 20000) {
            // ancestor is replaced by progeny closer to target or its identical offspring
            var newStr = mutateString(ancestorStr),
                newScore = getStringScore(newStr);
            if (newScore < ancestorScore) {
                ancestorStr = newStr;
                ancestorScore = newScore;
            }
            generationsHTML += generation + ': ' + ancestorStr + ' (' + ancestorScore + ')\n';
        }

        generationsElem.innerHTML = 'Total generations: ' + generation + '\n' + generationsHTML;
    }

    function mutateString(str, mutations)...