@0@6000000@5
}0&0&0&0&0
>0@6&3
\\--\/&2
@0/\@4\/&1!!
@4@1..@2@5@3
IIIIIIIIIIII
FF&1FF&2FF&3
@1OO@2OO@3OO
:I
}1..}10001F7
=9&1++..&1&0
&0}0&1&0{1{1
{>\/{0//
:O
}0
+Z
+C
{0
It works for only for values under 256 since Marbelous is an 8 bit language.
How it works
Marbelous is a 2D language with values represented by 8 bit marbles that fall down one cell on each tick unless some device prevents them from falling down. This Marbelous program consists of 3 boards; let's start with the easiest one:
:O
}0
+Z
+C
{0
:O
is the name of the board (to be precise, O is the name and : tells the interpreted that this line is a name. By giving boards a name, other boards can call on them
}0
is an input device, this can be seen as an argument of this function. This cell will get replaced by an input marble (value) when the function gets called.
+Z
adds 35 to any marble that passes over it and lets it fall through. +C
does the same but only adds 12. {0
is an output cell, when a marble reaches this cell, the function will exit and return the value in this output device.
So all together, this board takes one value and then adds 47 to it. For us this means it turns any single digit number into the ascii code of the digit -1 (this will of course also work for 10).
:I
}1 .. }1 00 01 F7
=9 &1 ++ .. &1 &0
&0 }0 &1 &0 {1 {1
{> \/ {0 //
This board is looking a bit more complicated. You should be able to identify :I
as the name of the board and have spotted some input and output devices. You'll notice that we have two different input devices, }0
and }1
. This means this function takes 2 inputs. You'll also notice that there are two instances of the }1
device. Upon calling the function, both of these cells will contain the same value. The }0
input device is directly above a \/
device, this acts as a trashcan and removes any marble that falls upon it immediately.
Let's have a look at what happens to one of the marbles put into the board by the }1
input devices:
}1
=9 &1
&0
{>
It will fall down on the first tick and hit the =9
device. This compares the value oif the marble to 9 and lets the marble fall through if the statement =9
evaluates to through. The marble gets pushed to the right if not. &0
and &1
are synchronizers. They hold on to marbles that fall onto them until all other &n
synchronizers are filled as well. As you can expect, this will conditionally trigger different behaviour on some other part of the board.
}1 00 01 F7
++ .. &1 &0
&1 &0 {1 {1
{0 //
If I tell you that ++
is an incrementor, you should already be able to tell what the different synchronizers will be filled with. The left &1
will contain the input value }1
+ 1, the &0
next to it will contain 0 (00
is a language literal, represented in hexadecimal). The second &1
will contain the value 1 and the right &0
gets filled with an F7
, which subtracts 9 from a value since addition in Marbelous is modulo 256.
//
is a deflector device, which pushes any marble to the left instead of letting it fall down.
Putting this all together gives you this: if the marble in }1
is 9, the &0
synchronizers get filled. This will cause the value 0 to fall into the {0
output and F7
(or -9) into the {1
output.
If }1
is not 9, {0
will be filled with }1
+ 1 and {0
will contain 1.
There is also a {>
device, this is a special output that outputs a marble next to a board in stead of underneath it. This will get filled with }1
if it equals 9.
@0 @6 00 00 00 @5
}0 &0 &0 &0 &0
>0 @6 &3
\\ -- \/ &2
@0 /\ @4 \/ &1 !!
@4 @1 .. @2 @5 @3
II II II II II II
FF &1 FF &2 FF &3
@1 OO @2 OO @3 OO
Okay, now for the big one. This board does not have an explicit name, since it is the main board of the file. Its implicit name is Mb
. You should be able to recognize some cells. There is an input device, some language literals (00
and FF
). There are some synchronizers and there's a deflector. lets step through this piece by piece.
@0 @6
}0 &0
>0 @6
\\ --
@0 /\ @4
So the input value (the command line input since this is the main board) starts at the second cell from the top where }0
is located. It will fall down and reach the >0
device, which is another comparison device. any marble larger than 0 falls through, any other marble gets pushed to the right. (since Marbelous variables are unsigned, only exactly 0 will get pushed to the right). This zero value marble will then hit the @6
device. This is a portal and transports the marble to another corresponding portal, in this case right above it. The 0 marble will then reach the &0
synchronizer and trigger some things elsewhere.
If the marble is not 0, it falls down, gets deflected to the right by \\
hits --
which decrements it by one and then falls onto /\
, a cloner. This device takes a marble and outputs one copy of it to the right and one to the left. The left one will be taken upwards to the other @0
where the marble will go through the same sequence again. The left one will be taken elsewhere.
This gives us a loop, which decrements the command line input once per loop and triggers some behaviour on every loop until it reaches 0. It then triggers some other behaviour.
Let's have a look at what happens with the marble pushed into @4
on each loop.
@4 @1 .. @2 @5 @3
II II II II II II
FF &1 FF &2 FF &3
@1 OO @2 OO @3 OO
There are 3 language literals here (FF
), which will immediately fall into portals. These portals will take them to three of the II
devices. II
refers to the board :I
we defined further down the file. Since :I
has 2 distinct input devices, it's representation on another board must be 2 cells wide. Since we have 6 cells containing II
, we cam tell we have 3 instances of this function on the board.
The FF
(or 256 or -1 if you will) marbles will sit in the input cells of the :I
function waiting untill there are enough input marble sto start the function (one more that is). That's where the @4
portal comes in. A copy of the decremented command line input falls through there on each loop. This will trigger the leftmost :I
board. Initialy with the values 256 (or -1) and whatever the command line input was -1. The left marble will be put into the }0
devices of the :I
board and the right one into the }1
. If you recall what this board did, you'll be able to tell what result this has. It will output an incremented version of the right input on the left output (and it turns a 9 into a 0, not 10) and outputs either 1 or -9 on the right.
The incremented value will be taken right back to the right input cell by a portal, and the value on the right falls into a synchronizer. If a synchronizer is already holding a marble, the two marbles will collide. Colliding marbles get added together modulo 256. So the values in the synchroizers will do the folowing: They start out empty, then turn to 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, and then to 1 again (since 247 gets added modulo 256).
You also might remember that a marble gets output to the right when the input value loops back to 0. Since the :I
boards are right next to each other, thsi will trigger the board to the right once. This will fill the three synchronizers with values that are one higher than they should be to be a shortlex representation of the command line input, by the time this has looped down to 0.
You might also remember that the :O
function turns a value into the ascii value of the digit that represents the value -1. The output of these OO
cells will then fall off the board, which prints their corresponding ascii chars to STDOUT.
00 00 00 @5
&0 &0 &0
&3
\/ &2
\/ &1 !!
@5
So what happens when the command line input marble reaches 0 and fills that &0
synchronizers? well, a few 0 value marbles fall down and trigger the three synchronizers that are holding the digits (+ 1) of the shortlex number at the bottom of the board. &3
gets triggered first, since it contain the most significant digit, then comes &2
followed by &1
. This marble then gets teleported to the other @5
device before eventually hitting the !!
cell, which terminates the board.
2It might be important to note that the sequence
19, 20, 21, 22
in decimal maps to08, 09, 10, 11
in shortlex. That's why I used confused that100 -> 89
! – Sean Latham – 2014-09-09T11:50:00.1132Related – Peter Taylor – 2014-09-09T15:51:49.153
6
Note that what you're calling the "shortlex decimal" of a number is also its bijective base-ten numeral, with symbols {0,1,2,3,4,5,6,7,8,9} substituted for the usual digits {1,2,3,4,5,6,7,8,9,A}. E.g, 2014 in the usual bijective base-ten notation is 1A14, and in shortlex decimal it is 0903.
– r.e.s. – 2014-09-10T03:22:11.443