This is a program written in Wonderlang, a silly language. The challenge is to run it. To do so, solvers must reverse engineer the mechanics of the language and the meanings of the symbols and identifiers.
Figuring those things out should require only analyzing the "include" files (burble, chortle, deficious, grabe, and slithy). Each of those defines one or two small functions which should be recognizable once the basics of the language are gleaned, and each helps to confirm some of the trickier parts of the language.
Once those are resolved, the final task is to evaluate the runme file. This is possible either by analyzing it in parts and porting it to another language, or by writing an interpreter for Wonderlang and running the program directly.
Here are some example expressions and their meanings:
Expression | Meaning |
46KJ | 12345 |
A 5 ♠ | 1 + 5 |
5 A ♣ | 5 - 1 |
2 5 ♥ | 2 * 5 |
A 2 ☊ | 1 < 2 |
A 2 ☋ | 1 > 2 |
A 2 ☺ | 1 == 2 |
J 3 ☁ | 11 modulo 3 |
‹sword› | The name 'sword' |
‹♙› | The name '♙' (chess pieces are also identifiers) |
sword | The value of the variable 'sword' |
{name} callay | Declare a variable |
{value} {name} uff | Assign a value to a variable |
{block} mome | Run {block} |
{blockA} {blockB} {value} gyre | If {value} is true, run {blockA} else run {blockB} |
∅ | An empty list |
{array} {value} gimble | An array like {array} but with {value} appended to it |
{array} {start} {count} munch | The subarray of {array} starting at {start} and having {count} values |
{arrayA} {arrayB} whiffle | An array consisting of the values of {arrayA} followed by the values of {arrayB} |
{array} frabjion | The length of {array} |
{array} {index} grend | The value at position {index} in {array} |
{name} plead | "Import" the named file, evaluating it immediately |
☞ blah blah ☜ | A comment |
This is a recursive algorithm for computing the Nth fibonacci number.
This is the Euclidian algorithm for computing the greatest common divisor.
This is a linear congruential generator using the formula:
X[n+1] = (10001 * X[n] + 12345) mod 65536
This implements a looping mechanism. It pops two "arguments", a code block B and a number N. It first calls B with N-1 (that is, N-1 will be the top value of the stack when B is called). Then it calls B again with N-2, then again with N-3, and so on until finally calling B with 0.
This is an implementation of quicksort. It pops an array of numbers and pushes a sorted version of that array.
Here are explanations for the variable names:
Variable | Purpose |
jabberwock | The data array which is manipulated to produce the answer phrase |
sword | An array of pseudo-randomly-generated numbers, used by frolick to shift the jabberwock data |
muchness | Sums all the elements of an array, used to help check progress |
snack | Function that produces the words of the answer phrase, by taking the first N values off the jabberwock array and pushing them onto the stack as an array |
tweedle | Reverses the jabberwock array |
frolick | Shifts each number in the jabberwock array by a corresponding entry in the sword array, using modulo to keep every element in the range 1-26 |
modge | "Unzips" the jabberwock array, moving every odd element to the first half and every even element to the second half |
priot | Starting at the end, in-place, subtracts from each element the element before it, and then adds 26 if the result is less than one |
The jabberwock array starts:
[20, 8, 5, 3, 25, 18, 16, 5, 5, 10, 17, 19, 24, 24, 5, 5, 11, 4, 9, 25, 2]
The sword array is:
[233, 4461, 7992, 9223, 16764, 21775, 22004, 22885, 24890, 31507, 33518, 39171, 42416, 48818, 51953, 52844, 62326, 63499]
First the jabberwock array is summed (using the muchness function). If the sum is not 260, the program returns [5, 18, 18, 15, 18] ("ERROR"). Then the sword array is summed. If the sum is not 556279, the program returns ERROR. These checks are to help check mistakes in those arrays.
The first three numbers are pulled:
[20, 8, 5] -> 'THE'
The remainder is then reversed (tweedled), and then shifted by the values in the sword array (frolicked):
tweedled: [2, 25, 9, 4, 11, 5, 5, 24, 24, 19, 17, 10, 5, 5, 16, 18, 25, 3] frolicked: [1, 14, 19, 23, 5, 18, 13, 3, 6, 14, 21, 25, 15, 21, 21, 4, 3, 10]
The first six numbers are pulled:
[1, 14, 19, 23, 5, 18] -> 'ANSWER'
The remainder is tweedled, then "unzipped" (modged), and then frolicked:
tweedled: [10, 3, 4, 21, 21, 15, 25, 21, 14, 6, 3, 13] modged: [10, 4, 21, 25, 14, 3, 3, 21, 15, 21, 6, 13] frolicked: [9, 19, 5, 18, 8, 16, 11, 26, 23, 16, 10, 2]
The first two numbers are pulled:
[9, 19] -> 'IS'
The remainder is tweedled, modged, prioted, and frolicked, and all ten numbers are pulled revealing the answer:
tweedled: [2, 10, 16, 23, 26, 11, 16, 8, 18, 5] modged: [2, 16, 26, 16, 18, 10, 23, 11, 8, 5] prioted: [2, 14, 10, 16, 2, 18, 13, 14, 23, 23] frolicked: [1, 5, 20, 9, 22, 5, 21, 19, 5, 18] -> 'ACTIVEUSER'
Here is a python implementation of a Wonderlang interpreter, which can run the runme.wl.html file directly.
Here is a Wonderlang-to-PostScript converter (written by Chieu Nguyen).