A 19th century painting of a weasel.

Animating Text with Dawkins' Weasel

Amanvir ParharMarch 18, 2025

Recently, I found this YouTube video that explained how you could create a "hacker" text scramble effect with some HTML, CSS, and Javascript.

Click on the text below to see what I'm talking about:

METHINKS IT IS LIKE A WEASEL

It's pretty cool. It works by first creating strings of random characters with the same length as our desired string and then iteratively "fixing" a character in each subsequent random generation to its actual value in our target string. This process is performed from left to right until the displayed string is equal to the target string:

UQZFDIHLCEVHJVTX KQUOLFOPKPP
MMYPMXUJKNIYXDPABTOLIKZYALFT
MEZWAVQJRUEGZZKJDXYHWORVUXDQ
...
METHINKS IT IS LIKE A WEASBS
METHINKS IT IS LIKE A WEASEZ
METHINKS IT IS LIKE A WEASEL

It's a simple algorithm, but it got me thinking about other ways you could scramble/unscramble text that would make for even cooler animations. My mind ended up going somewhere entirely unexpected...

In this brief blog post, I'll discuss Dawkins' weasel, a computer simulation theorized by evolutionary biologist Richard Dawkins to explain the essence of natural selection, and how I tweaked it to achieve an effect like this (click on the text below):

METHINKS IT IS LIKE A WEASEL

What is Dawkins' weasel?

I was surprised to learn that Richard Dawkins was once an avid computer programmer after watching one of his interviews on YouTube. Upon hearing this, I began digging into some of the code that Prof. Dawkins had written, and I landed upon the Wikipedia page for his namesake weasel program:

First mentioned in chapter 3 of his third published work, The Blind Watchmaker, the weasel program is a thought experiment based on the infinite monkey theorem:

I don't know who it was first pointed out that, given enough time, a monkey bashing away at random on a typewriter could produce all the works of Shakespeare. The operative phrase is, of course, given enough time. Let us limit the task facing our monkey somewhat. Suppose that he has to produce, not the complete works of Shakespeare but just the short sentence 'Methinks it is like a weasel', and we shall make it relatively easy by giving him a typewriter with a restricted keyboard, one with just the 26 (capital) letters, and a space bar. How long will he take to write this one little sentence?

In this scenario, we start off by generating a random sequence that:

  1. Only contains capital letters and spaces (a set of 27 characters).
  2. Has the same length as the "target" sequence (METHINKS IT IS LIKE A WEASEL is 28 characters long).

Under these two conditions, the probability of generating sequence of characters at random and landing upon a combination that's identical to the target sequence is astronomically small:

\frac{1}{27^{28}}

This scenario represents a common misunderstanding of genetic change under the theory of evolution. Skeptics of natural selection often rely on this inaccurate interpretation of evolution to show how improbable it would be for any complex life to arise, assuming that the theory is true.

The key flaw in this model is that it fails to account for the environment's influence on each string generation. A more accurate model of evolution would select for individuals who possess traits that are better suited to their surrounding environment. In our case, "more suitable" strings would be those that are more similar to target string.

With this in mind, we can create a weasel program that (while still being rather simplistic) more accurately reflects the theory of evolution:

  1. Randomly generate a string with 28 characters (as we laid out before).
  2. Generate n "offspring" of this string, where an offspring is a copy of the parent string with an m % chance of a "mutation" occurring for each character. A mutation would involve a particular character being replaced with a random character from the character set.
  3. Compare each offspring with the target string, and pick the one that most closely resembles the target string (we can measure this similarity using a metric like Hamming distance for this).
  4. If the most similar string from step 3 is identical to the target string, we can stop. Otherwise, repeat the process by going to step 2 and generating offspring of the most similar string.

Here's an example of what this might look like:

Randomly generated string: RLTIWVMQPSODUQMLJZAUFPFEAVTP

Best offspring from generation 1: RLTIWVMQPSODUQMLJZAUAPFEAVTP

Best offspring from generation 2: RLTIWVMQPSODUFMLJZAUAPFEAVTP

...

Best offspring from generation 82: YETHINKS IT IS LIKE A WEASEL

Best offspring from generation 83: METHINKS IT IS LIKE A WEASEL

For this specific example, I set n = 100, m = 0.05, but these values can be tweaked to your liking.

Fortunately, due to advances in computing, executing a program that implements this algorithm would take up far less time than it did for Prof. Dawkins:

If you want to know, it completed the whole exercise for me, the first time, while I was out to lunch. It took about half an hour. (Computer enthusiasts may think this unduly slow. The reason is that the program was written in BASIC, a sort of computer baby-talk. When I rewrote it in Pascal, it took 11 seconds.)

But, the stopwatch time doesn't really matter. As Prof. Dawkins points out, the weasel approach to modeling natural selection would require far fewer string generations to end up with a string that matches the target string, as opposed to our original method of generating strings with random variation but without cumulative selection:

Computers are a bit faster at this kind of thing than monkeys, but the difference really isn't significant. What matters is the difference between the time taken by cumulative selection, and the time which the same computer, working flat out at the same rate, would take to reach the target phrase if it were forced to use the other procedure of single-step selection: about a million million million million million years. This is more than a million million million times as long as the universe has so far existed.

Creating the text scramble animation

It turns out that you can get a pretty unique text scramble animation by making use of Dawkins' weasel.

Instead of printing the closest match from each generation one-by-one, we can update a single string with each generation's best match and display this string on the webpage.

Here's some Javascript code to accomplish this...

1
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ',
2
  n = 100,
3
  m = 0.05,
4
  sleepMs = 30;
5

6
let weaselEffectInterval,
7
  weaselTarget = 'METHINKS IT IS LIKE A WEASEL',
8
  currWeaselText = weaselTarget;
9

10
function animateWithDawkinsWeasel() {
11
  clearInterval(weaselEffectInterval);
12

13
  let newWeaselText = '';
14
  for (let i = 0; i < weaselTarget.length; i++) {
15
    newWeaselText += charset[Math.floor(Math.random() * charset.length)];
16
  }
17
  currWeaselText = newWeaselText;
18

19
  weaselEffectInterval = setInterval(() => {
20
    let offspringArr = [],
21
      offspringIdx = 0;
22

23
    while (offspringIdx < n) {
24
      offspringArr.push(
25
        currWeaselText
26
          .split('')
27
          .map((letter, i) => {
28
            return Math.random() <= m
29
              ? charset[Math.floor(Math.random() * charset.length)]
30
              : letter;
31
          })
32
          .join('')
33
      );
34
      offspringIdx++;
35
    }
36

37
    let maxMatchingChars = 0;
38

39
    for (const [i, offspring] of offspringArr.entries()) {
40
      let numMatchingChars = 0;
41

42
      for (const [j, char] of [...offspring].entries()) {
43
        if (weaselTarget[j] === char) numMatchingChars++;
44
      }
45

46
      if (numMatchingChars > maxMatchingChars) {
47
        currWeaselText = offspringArr[i];
48
        maxMatchingChars = numMatchingChars;
49
      }
50
    }
51

52
    if (currWeaselText == weaselTarget) clearInterval(weaselEffectInterval);
53
  }, sleepMs);
54
}

And here's how I'm displaying this text in my markup using Svelte (v4)...

1
<pre
2
  on:click={animateWithDawkinsWeasel}
3
  on:mouseenter={animateWithDawkinsWeasel}
4
>
5
{currWeaselText}
6
</pre>

Which ultimately produces this:

METHINKS IT IS LIKE A WEASEL

Final thoughts

I appreciate you reading this far! This was a fun article to write, as I'm a big fan of Prof. Dawkins—I actually attended one of his live shows for his last-ever American tour a few months ago:

Photos I took from Richard Dawkins' live show.

I'd highly recommend reading at least one of his books or watching one of his interviews (I find his conversation with Alex O'Connor to be especially interesting); both his writing and his speeches have had a hand in shaping the way I think and view the world.

I hope you enjoyed reading this post. If you'd like to check out some of my other work, please go here. If you want to get in touch, you can reach me on social media—Instagram, X/Twitter, Bluesky, LinkedIn—or through email: amanvir.com [at] gmail [dot] com.

References


Hey, my name is Amanvir Parhar (but you can call me Aman)! I'm an undergrad studying C.S. at the University of Maryland, College Park.

If you liked this post, feel free to check out my other work. You can reach out to me on X/Twitter, Bluesky, Instagram, LinkedIn, or through email: amanvir.com [at] gmail [dot] com.

© 2025 Amanvir Parhar. All rights reserved.