I wrote a book called If Hemingway Wrote JavaScript in which I imagine 25 famous novelists, poets and playwrights solving simple problems in JavaScript. It’s part homage to my favorite writers and part love letter to JavaScript, the only language I know with enough freedom, creative potential and downright quirkiness to pique the interest of the literary greats.

This post contains original material that’s not in the book (think of it as one of those “behind the scenes” bonus features). It’s the first in a series of deep technical dives into each author’s solution. Some solutions require more explanation than others.

Enjoy!

Part 1: Prime Numbers

1. Jorge Luis Borges

2. Lewis Carroll

3. Douglas Adams

4. Charles Dickens

5. David Foster Wallace

6. Wrap Up / About the Book

The assignment: write a function that returns all the prime numbers up to the value of the supplied argument.

1. Jorge Luis Borges

https://github.com/angus-c/literary.js/tree/master/book/borges/prime.js

// They speak (I know) of finials, newels and balustrades // of hidden spandrels and eternally clambering, broad-gaited beasts... var monstersAscendingAStaircase = function(numberOfSteps) { var stairs = []; stepsUntrodden = []; var largestGait = Math.sqrt(numberOfSteps); // A succession of creatures mount the stairs; // each creature's stride exceeds that of its predecessor for (var i = 2; i <= largestGait; i++) { if (!stairs[i]) { for (var j = i * i; j <= numberOfSteps; j += i) { stairs[j] = "stomp"; } } } // Long-limbed monsters won't tread on prime numbered stairs. for (var i = 2; i <= numberOfSteps; i++) { if(!stairs[i]) { stepsUntrodden.push(i); } } // Here, then, is our answer. return stepsUntrodden; };

Borges’ solution is a variation on the Sieve of Eratosthenes algorithm by which the multiples of each known prime are marked as composite (non-prime). In this case, Borges has long legged monsters take the place of divisors. Each monster straddles one more stair than the monster that went before: 2, 3, 4, 5…up to the square root of the number of the highest stair. (for non-obvious reasons, Borges allows composite-gaited monsters to climb the stairs too). The untrodden stairs are the prime numbers.

Notice on line 12 that each monster starts its ascent from the square of its factor:

for (var j = i * i; j <= numberOfSteps; j += i) {

That’s because composites between n and n² will already have been trodden by monsters with smaller strides.

2. Lewis Carroll

https://github.com/angus-c/literary.js/tree/master/book/carroll/prime.js

function downTheRabbitHole(growThisBig) { var theFullDeck = Array(growThisBig); var theHatter = Function('return this/4').call(2*2); var theMarchHare = Boolean('The frumious Bandersnatch!'); var theVerdict = 'the white rabbit'.split(/the march hare/).slice(theHatter); //into the pool of tears... eval(theFullDeck.join('if (!theFullDeck[++theHatter]) {\ theMarchHare = 1;\ theVerdict.push(theHatter);\ ' + theFullDeck.join('theFullDeck[++theMarchHare * theHatter]=true;') + '}') ); return theVerdict; }

As with his writing, most of Carroll’s solution is either riddle or nonsense. Let’s decipher it line-by-line, starting with the variable declarations.

Line 2 is actually fairly conventional (if we overlook the use of an Array constructor). Carroll’s creating an empty array whose length matches the supplied argument. It’s called theFullDeck because his solution imagines a pack of playing cards for which only the prime numbers will remain face-up at the end.

Line 3 creates a function (using the little-used Function constructor) and then invokes it with call, passing 2 * 2 (i.e., 4) as the this argument. Thus theHatter is initialized to 1.

Line 4 sets the theMarchHare to true. When the Boolean constructor is called as a function it converts its argument to either true or false. In this case the non-empty string ‘The frumious Bandersnatch!’ is converted to true. (Notice by the way, that this assignment is quite unnecessary because a fresh value is assigned to theMarchHare in line 10).

Finally, and perhaps most absurdly, in line 6 Carroll assigns an empty array to theVerdict in a decidedly roundabout fashion:

var theVerdict = 'the white rabbit'.split(/the march hare/).slice(theHatter);

There’s actually less here than meets the eye. The argument to split is a regular expression that doesn’t match ‘the white rabbit’, so invoking that split yields an array containing only ‘the white rabbit’. The subsequent slice operation populates a copy of the array with all the members of the original array, starting from the supplied index. Since our one-element array doesn’t have an index of 1 (the value of theHatter), no members are copied from it, and so the result is an empty array.

Simplifying, we could rewrite the variable declarations like this:

function downTheRabbitHole(growThisBig) { var theFullDeck = Array(growThisBig); var theHatter = 1; var theMarchHare = true; var theVerdict = [];

Now to the really wacko part:

//into the pool of tears... eval(theFullDeck.join('if (!theFullDeck[++theHatter]) {\ theMarchHare = 1;\ theVerdict.push(theHatter);\ ' + theFullDeck.join('theFullDeck[++theMarchHare * theHatter]=true;') + '}') );

Before we get to the much maligned eval function, let’s focus on the nested join statements. The join function turns an array into a string, using its argument as the glue between each array member. Calling join over an empty array results in a string composed entirely of the glue (repeated n – 1 times, where n is the length of the array):

Array(4).join('hi'); //'hihihi'

If we nest two joins then the respective glues are nested:

Array(4).join('A' + Array(4).join('a')); //'AaaaAaaaAaaa'

By including variables in the glue, we can start to get clever:

var arr = [], count = 0; Array(4).join('arr.push(' + Array(4).join('count++,') + '-1);'); //"arr.push(count++,count++,count++,-1);arr.push(count++,count++,count++,-1);arr.push(count++,count++,count++,-1)"

Now that we’ve taught JavaScript how to generate JavaScript, we just need a way to run it. Enter the dastardly eval…

var arr = [], count = 0; eval(Array(4).join('arr.push(' + Array(4).join('count++,') + '-1);')); arr; //[0, 1, 2, -1, 3, 4, 5, -1, 6, 7, 8, -1]

…and this is the strategy Carroll uses to auto-generate a prime number program. Let’s take another look at his code:

//into the pool of tears... eval(theFullDeck.join('if (!theFullDeck[++theHatter]) {\ theMarchHare = 1;\ theVerdict.push(theHatter);\ ' + theFullDeck.join('theFullDeck[++theMarchHare * theHatter]=true;') + '}') );

The argument to eval resolves (after formatting) to:

if (!theFullDeck[++theHatter]) { theMarchHare = 1; theVerdict.push(theHatter); theFullDeck[++theMarchHare * theHatter] = true; theFullDeck[++theMarchHare * theHatter] = true; theFullDeck[++theMarchHare * theHatter] = true; } if (!theFullDeck[++theHatter]) { theMarchHare = 1; theVerdict.push(theHatter); theFullDeck[++theMarchHare * theHatter] = true; theFullDeck[++theMarchHare * theHatter] = true; theFullDeck[++theMarchHare * theHatter] = true; } if (!theFullDeck[++theHatter]) { theMarchHare = 1; theVerdict.push(theHatter); theFullDeck[++theMarchHare * theHatter] = true; theFullDeck[++theMarchHare * theHatter] = true; theFullDeck[++theMarchHare * theHatter] = true; } // etc...

…and so on. (This generated code can get extremely long. A request for all the prime numbers up to 100 generates over 10,000 lines of code–with obvious performance implications–but we’re in Wonderland, so it’s ok. I guess.)

Anyway, gradually the mists are clearing. It turns out Carroll is applying a flavor of the same Sieve of Eratosthenes algorithm that was used by Borges. theFullDeck is an array representing every number to be tested, theHatter and theMarchHare are nested counters that are multiplied on every increment so as to generate every possible composite number. At the index of each composite number, the card is turned over (i.e. theFullDeck at that index is marked true). The remaining face-up cards are the primes.

3. Douglas Adams

https://github.com/angus-c/literary.js/tree/master/book/adams/prime.js

// Here I am, brain the size of a planet, and they ask me to write JavaScript... function kevinTheNumberMentioner(_){ l=[] /* mostly harmless --> */ with(l) { // sorry about all this, my babel fish has a headache today... for (ll=!+[]+!![];ll<_+(+!![]);ll++) { lll=+!![]; while(ll%++lll); // I've got this terrible pain in all the semicolons down my right hand side (ll==lll)&&push(ll); } forEach(alert); } // you're really not going to like this... return [!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]; }

Most of Adams’ solution is hard to read because the syntax borrows heavily from jsfuck, an ingenious yet upsetting little language that uses just 6 characters. Nevertheless it’s also valid JavaScript—if you run it in your console, it works. Let’s translate a short snippet:

for (ll=!+[]+!![];ll<_+(+!![]);ll++) {

This is a for loop and ll and _ are the names of variables. Everything else is literal and figurative brainfuck.

In the first clause of the statement, ll is assigned the value !+[]+!![]. Deconstructing that expression we can see there are two empty array literals. The first array literal is preceded by a + which coerces it to the number 0. Right before that there’s a ! which coerces the 0 to its boolean opposite, i.e., true. So !+[] resolves to true.

Now let’s look at the second array literal. It’s preceded by two !!s which will simply coerce it to a Boolean. Because arrays are always objects, the Boolean of an array is always true (see es5’s ToBoolean). So !![] also resolves to true.

Putting those two expressions together, !+[]+!![] is equivalent to true + true. Here the + coerces both operands to the number 1 so the expression ultimately resolves to 2.

The other two clauses of the for loop are now relatively easy to figure out. Again we see !![], this time preceded by a + which coerces true to 1. So ll<_+(+!![]) resolves to ll < _ + 1.

The final clause reads as a regular JavaScript postfix and so the entire for loop resolves to:

for (ll = 2; ll < _ + 1; ll++) {

Here’s the entire solution translated into regular earthling JavaScript. (I’ve also given the variables more meaningful names.)

// Here I am, brain the size of a planet, and they ask me to write JavaScript... function kevinTheNumberMentioner(max){ var result = []; /* mostly harmless --> */ with(result) { // sorry about all this, my babel fish has a headache today... for (candidate = 2; candidate < max + 1; candidate++) { var factor = 1; while (candidate % ++factor); // I've got this terrible pain in all the semicolons down my right hand side (candidate == factor) && push(candidate); } forEach(alert); } // you're really not going to like this... return '42'; }

OK, so now it’s recognizable JavaScript at least, but there are a number of lingering oddities.

The with statement is one of those language features that the JavaScript Police frown upon, and yet there’s one right there on line 3. JavaScript will attempt to scope all unreferenced properties within the with block to the given object. Thus the disturbingly orphaned array methods push and forEach will be scoped to result.

Another curious statement is the while loop on line 9. The loop has no body, so factor just keeps incrementing until it divides exactly into the candidate number. The next line checks if candidate now has the same value as factor. If it does, the number has no lesser factors so must be prime, and it’s added to result.

Line 13 loops through the result and shouts out each prime number in the form of an alert. Finally the program returns 42.

4. Charles Dickens

https://github.com/angus-c/literary.js/tree/master/book/dickens/prime.js

function MrsPrimmerwicksProgeny(MaxwellNumberby) { Number.prototype.isAPrimmerwick = function() { for (var AddableChopper = 2; AddableChopper <= this; AddableChopper++) { var BittyRemnant = this % AddableChopper; if (BittyRemnant == 0 && this != AddableChopper) { return console.log( 'It is a composite. The dear, gentle, patient, noble', +this, 'is a composite'), false; } } return console.log( 'Oh', +this, +this, +this, 'what a happy day this is for you and me!'), true; } var VenerableHeap = []; for (var AveryNumberby = 2; AveryNumberby <= MaxwellNumberby; AveryNumberby++) { if (AveryNumberby.isAPrimmerwick()) { VenerableHeap.push(AveryNumberby); } } return VenerableHeap; }

Imagine if you could just ask a number if it’s a prime:

6..isPrime(); //false 7..isPrime(); //true

By extending Number.prototype that’s exactly what Charles Dickens does. His custom extension is called isAPrimmerwick (and in fact all his objects have quirky Dickensian names) and it’s defined on lines 2-14. Lines 17-21 simply ask each number if it’s a prime, and adds those that are to the results array which is called VenerableHeap.

The logic of the isAPrimmerwick method is mostly straightforward. The number in question is divided by each possible factor. If any division yields a zero remainder then the number is deemed composite (non-prime), else it’s a prime.

There are a couple of curiosities in each return statement (lines 6 and 11). First, since the number is calling a method on its own prototype, it can be referenced by this (but with a prefixed + to coerce it from a Number object to a primitive). Second, Dickens uses the comma operator to simultaneously invoke console.log and return a Boolean value.

5. David Foster Wallace

https://github.com/angus-c/literary.js/tree/master/book/wallace/prime.js

var yearOfTheLighteningQuickAtkinSieve = function(tops) { //B.P. #40 07-14 //ELEPHANT BUTTE, NM var NSRS/*[1]*/ = [0,0,2,3]; /* Two concurrent loops are mobilized such that the variables i and j (each having an initial value of 1) are incremented by steps of 1 (though in a nested fashion). */ for(var i = 1; i < Math.sqrt(tops); i++){ for(var j = 1; j < Math.sqrt(tops); j++){ if (i*i + j*j >= tops) { break; } /* The two variables (i.e. i and j) are injected into the first quadratic, the result being assigned to the additional variable (n). */ var n = 4*i*i + j*j; /* Should the additional variable (i.e. n) yield, when divided by 12, a remainder of 1 or 5, the value at that index (i.e. n's) is flipped [2]. */ if(n <= tops && (n%12 == 1 || n%12 == 5)){ NSRS[n] = NSRS[n] ? 0 : n; } /* Now, we (i.e. JavaScript) reach the second quadratic and again the result is assigned to the (existing) variable n. */ n = 3*i*i + j*j; /* Although the variable (i.e. n) is again divided by 12, this time the remainder is checked against 7 to determine whether the indexed value (i.e. the value at n) needs flipping. */ if(n <= tops && (n % 12 == 7)){ NSRS[n] = NSRS[n] ? 0 : n; } /* By now you (i.e. the reader) are no doubt experiencing feelings of ambivalence and regret, nevertheless, we (i.e. JavaScript) haven't finished yet. Predictably, a third quadratic is now run and (equally predictably) it's value assigned to the (now world weary) variable, n. */ n = 3*i*i - j*j; /* The only interesting thing about the third division (though also the depressing thing) is that it only happens when the first looping variable (i) is greater than i.e. not less than (or equal to) the second looping variable (j) [3]. */ if (i>j) { if((n <= tops) && (n % 12 == 11)){ NSRS[n] = NSRS[n] ? 0 : n; } } } } /* Near exhaustion (yet distrustful of the quadratic wheel factorization filter) we (i.e. JavaScript) now designate any and all prime factors, w/o regard for their current prime, or composite (i.e. non-prime) designation, as being composite (i.e non-prime) */ for(i = 5; i < Math.sqrt(tops); i++){ if(NSRS[i] == 1){ for(j = i*i; j < tops; j += i*i){ NSRS[j] = 0; } } } return NSRS.filter(Number); // [4] } /* [1] Numeric Storage and Retrieval System. [2] Meaning values representing the current index [a] are set to 0, while values of 0 are set to the current index. [3] Otherwise each relevant index [a] would be flipped twice. [4] `Array.prototype.filter` being a higher order function defined by The EcmaScript-262 Standard (5th edition) [b]. Since `Number` is a built-in function that converts any value to a number and Array.prototype.filter rejects falsey (i.e. not truthy) values, thus values of 0, being falsey (i.e. not truthy) will not be included in the array returned by `Array.prototype.filter`. [a] i.e. an index for which the quadratic in question resolves to true. [b] http://es5.github.io/#x15.4.4.20 */

Thanks to Wallace’s famously abundant commentary, there’s not much left for me to describe here–except to say that his solution is based on the highly optimized (and too complicated to explain here) Sieve of Atkin (Wallace’s solution in particular owes a lot to this gist by Mohammad Shahrizal Prabowo).

The code is most notable for the elaborate logic and Wallace’s precise yet conversational annotation, but there’s also JavaScript interest down on line 54:

return NSRS.filter(Number); // [4]

NSRS is the result. At this point it’s a sparse array containing all the prime numbers, but interleaved with undefined values (and front-buffered with zeros):

[0, 0, 2, 3, undefined, 5, undefined, 7/*, etc.. */]

Array.prototype.filter creates a new array containing only those members of the original array for which the given function returns a truthy value. In this case the given function is Number, a built-in function that attempts to coerce its argument to a number. Number coerces undefined to NaN while leaving all genuine numbers untouched. Since both NaN and 0 are falsey values, the new array will contain only prime numbers:

[0, 0, 2, 3, undefined, 5, undefined, 7].filter(Number); //[2, 3, 5, 7]

Wrap Up / About the Book

And that’s that for Part 1. Hope you had fun and if you had any questions or notice any mistakes, feel free to add a comment, or tweet me at @angustweets

If you’ve enjoyed this or any of my previous posts on this site, consider buying a copy of If Hemingway Wrote JavScript. It’s beautifully designed and printed, and each of the twenty-five sections includes an original biography of the author, their imagined JavaScript solution, a code review and a gorgeous illustration by Miran Lipovača (of Learn Yourself a Haskell fame). Thanks!