Solution to Callooh Callay, World!

Author: James Clark

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.

The Basics

This is a stack-oriented language which uses postfix notation. For the most part, each token pushes a value onto the stack, but some reserved symbols and identifiers perform other operations. In addition to the stack, values can be stored in scoped variables. '‹' and '›' are used to push the names of variables (as opposed to the values) onto the stack. '«' and '»' denote blocks of code, which are pushed onto the stack as well. The number system is base 14, using the digits 0A23456789TJQK. Arrays are zero-indexed. Reserved identifiers are rendered in italics to help distinguish them from variable names.

Here are some example expressions and their meanings:
ExpressionMeaning
46KJ12345
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)
swordThe value of the variable 'sword'
{name} callayDeclare a variable
{value} {name} uffAssign a value to a variable
{block} momeRun {block}
{blockA} {blockB} {value} gyreIf {value} is true, run {blockA} else run {blockB}
An empty list
{array} {value} gimbleAn array like {array} but with {value} appended to it
{array} {start} {count} munchThe subarray of {array} starting at {start} and having {count} values
{arrayA} {arrayB} whiffleAn array consisting of the values of {arrayA} followed by the values of {arrayB}
{array} frabjionThe length of {array}
{array} {index} grendThe value at position {index} in {array}
{name} plead"Import" the named file, evaluating it immediately
☞ blah blah ☜A comment

slithy.wl

This is a recursive algorithm for computing the Nth fibonacci number.

grabe.wl

This is the Euclidian algorithm for computing the greatest common divisor.

deficious.wl

This is a linear congruential generator using the formula:

  X[n+1] = (10001 * X[n] + 12345) mod 65536

chortle.wl

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.

burble.wl

This is an implementation of quicksort. It pops an array of numbers and pushes a sorted version of that array.

runme.wl

This is a set of functions that generate the answer phrase from a hard-coded array of "ciphertext". It is designed so that it is possible to see the lengths of the words in the phrase in advance, and so each word of the answer phrase requires a little more to be figured out. The idea being that if the solver is porting the code and introduces a bug, they should have only a limited piece of code to debug.

Here are explanations for the variable names:
VariablePurpose
jabberwockThe data array which is manipulated to produce the answer phrase
swordAn array of pseudo-randomly-generated numbers, used by frolick to shift the jabberwock data
muchnessSums all the elements of an array, used to help check progress
snackFunction 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
tweedleReverses the jabberwock array
frolickShifts 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
priotStarting 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).

Here is a python implementation of runme.wl.