Explanation
Alice has a built-in bijection between Zℤ and Zℤ2, which can be computed with Y
(unpack) and its inverse (pack). We simply applyHere is an excerpt from the docs explaining the bijection:
The details of the bijection are likely irrelevant for most use cases. The main point is that it lets the user encode two integers in one and extract the two integers again later on. By applying the pack command repeatedly, entire lists or trees of integers can be stored in a single number (although not in a particularly memory-efficient way). The mapping computed by the pack operation is a bijective function ℤ2 → ℤ (i.e. a one-to-one mapping). First, the integers {..., -2, -1, 0, 1, 2, ...} are mapped to the natural numbers (including zero) like {..., 3, 1, 0, 2, 4, ...} (in other words, negative integers are mapped to odd naturals and non-negative integers are mapped to even naturals). The two natural numbers are then mapped to one via the Cantor pairing function, which writes the naturals along the diagonals of the first quadrant of the integer grid. Specifically, {(0,0), (1,0), (0,1), (2,0), (1,1), (0,2), (3,0), ...} are mapped to {0, 1, 2, 3, 4, 5, 6, ...}. The resulting natural number is then mapped back to the integers using the inverse of the earlier bijection. The unpack command computes exactly the inverse of this mapping.
As alluded to above, we can use this unpack operation to map ℤ to ℤk as well. After applying it to the initial integer, we can unpack the second integer of the result again, which gives us a list of three integers. So k-1 times toapplications of Y
give us k integers as the inputresult. I'll add an explanation
We can compute the inverse by packing the list up with Z
from the end.
So the program itself has this structure:
/O
\i@/...d&
This is just a basic template for a program which reads a variable number of decimal integers as input and prints a variable number as the result. So the actual code is really just:
t Decrement k.
& Repeat the next command k-1 times.
Y Unpack.
One thing I'd like to address is "why would Alice have a built-in for a ℤ → ℤ2 bijection later, isn't that golfing language territory"? As with most of Alice's weirder built-ins, the main reason is Alice's design principle that every command has two meanings, one for Cardinal (integer) mode and one for Ordinal (string) mode, and these two meanings should be somehow related to give Cardinal and Ordinal mode the feeling that they are mirror universes where things are sort of the same but you can find it inalso different. And quite often I had a command for one of the docs undertwo modes I wanted to add, and then had to figure out what other command to pair it with.
In the case of Y
and Z
commandsOrdinal mode came first: I wanted to have a function to interleave two strings (zip) and separate them again (unzip). The quality of this that I wanted to capture in Cardinal mode was to form one integer from two and be able to extract the two integers again later, which makes such a bijection the natural choice.
I also figured that this would actually be very useful outside of golfing, because it lets you store an entire list or even tree of integers in a single unit of memory (stack element, tape cell or grid cell).