Pure Sourcery - Shaping programs that output the digits 0 through 9

Here's a pixelated 5 by 7 font for the digits 0 through 9:

.███.
█...█
█...█
█...█
█...█
█...█
.███.

..█..
███..
..█..
..█..
..█..
..█..
█████

.███.
█...█
....█
...█.
..█..
.█...
█████

.███.
█...█
....█
..██.
....█
█...█
.███.

█..█.
█..█.
█..█.
█████
...█.
...█.
...█.

█████
█....
█....
.███.
....█
█...█
.███.

.███.
█...█
█....
████.
█...█
█...█
.███.

█████
....█
....█
...█.
...█.
..█..
..█..

.███.
█...█
█...█
.███.
█...█
█...█
.███.

.███.
█...█
█...█
.████
....█
█...█
.███.


(This font and this page will probably look better if you run this JavaScipt code in your browsers console or in the URL bar prefixed by javascript:: $('#question pre,.answer pre').css('line-height',1).) Write two equal sized rectangular blocks of text, one to represent the empty spaces (.) in the font above, and one to represent the filled spaces (█). When these two text blocks are arranged into the same 5×7 pattern as one of the digits above, then the resulting large text block should be a program that prints that digit to stdout. This should work for all 10 digits. For example, if your . text block was --- '''  and your █ text block was ABC 123  then the program ---ABCABCABC--- '''123123123''' ABC---------ABC 123'''''''''123 ABC---------ABC 123'''''''''123 ABC---------ABC 123'''''''''123 ABC---------ABC 123'''''''''123 ABC---------ABC 123'''''''''123 ---ABCABCABC--- '''123123123'''  should output 0. Similarly, the program ------ABC------ ''''''123'''''' ABCABCABC------ 123123123'''''' ------ABC------ ''''''123'''''' ------ABC------ ''''''123'''''' ------ABC------ ''''''123'''''' ------ABC------ ''''''123'''''' ABCABCABCABCABC 123123123123123  should output 1, and so on up to the program for 9. You can use this stack snippet to make the digit shaped programs: <style>textarea{font-family:monospace;}</style><script>function go(){var t=parseInt(document.getElementById("digit").value[0]);if(isNaN(t))return void alert("Invalid digit.");for(var e=document.getElementById("empty").value.split("\n"),n=document.getElementById("filled").value.split("\n"),l=[],o=0;o<7*e.length;o++){l[o]="";for(var d=0;5>d;d++)l[o]+=font[t][Math.floor(o/e.length)][d]?n[o%n.length]:e[o%e.length]}document.getElementById("output").value=l.join("\n")}font=[[[0,1,1,1,0],[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[0,1,1,1,0]],[[0,0,1,0,0],[1,1,1,0,0],[0,0,1,0,0],[0,0,1,0,0],[0,0,1,0,0],[0,0,1,0,0],[1,1,1,1,1]],[[0,1,1,1,0],[1,0,0,0,1],[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,1,1,1,1]],[[0,1,1,1,0],[1,0,0,0,1],[0,0,0,0,1],[0,0,1,1,0],[0,0,0,0,1],[1,0,0,0,1],[0,1,1,1,0]],[[1,0,0,1,0],[1,0,0,1,0],[1,0,0,1,0],[1,1,1,1,1],[0,0,0,1,0],[0,0,0,1,0],[0,0,0,1,0]],[[1,1,1,1,1],[1,0,0,0,0],[1,0,0,0,0],[0,1,1,1,0],[0,0,0,0,1],[1,0,0,0,1],[0,1,1,1,0]],[[0,1,1,1,0],[1,0,0,0,1],[1,0,0,0,0],[1,1,1,1,0],[1,0,0,0,1],[1,0,0,0,1],[0,1,1,1,0]],[[1,1,1,1,1],[0,0,0,0,1],[0,0,0,0,1],[0,0,0,1,0],[0,0,0,1,0],[0,0,1,0,0],[0,0,1,0,0]],[[0,1,1,1,0],[1,0,0,0,1],[1,0,0,0,1],[0,1,1,1,0],[1,0,0,0,1],[1,0,0,0,1],[0,1,1,1,0]],[[0,1,1,1,0],[1,0,0,0,1],[1,0,0,0,1],[0,1,1,1,1],[0,0,0,0,1],[1,0,0,0,1],[0,1,1,1,0]]]</script><textarea id='empty' rows='8' cols='32' placeholder='empty space text block...'></textarea><textarea id='filled' rows='8' cols='32' placeholder='filled space text block...'></textarea><br>Digit <input id='digit' type='text' value='0'> <button type='button' onclick='go()'>Generate</button><br><br><textarea id='output' rows='16' cols='64' placeholder='output...' style='background-color: #eee;' readonly></textarea> Details • None of the 10 large text block programs should require input. Only output the single digit plus an optional trailing newline. Output to stdout or a similar alternative. • None of the programs may read or access their own source code. Treat this like a strict quine challenge. • The text blocks may not be identical and must have nonzero dimensions. • The text blocks may contain any characters except line terminators. • The 10 programs must be full-fledged programs written in the same language, they are not REPL snippets. You may optionally add a trailing newline to all of them or none of them. Scoring Your score is the area (width times height) of one of your text blocks. (They are the same size so there's no point in counting both blocks.) The area of the example is 3 by 2, for a score of 6. The lowest score wins. In case of ties, the highest-voted answer wins. • On your code, you can improve it a lot. var t=parseInt(document.getElementById("digit").value[0]);if(isNaN(t))return void alert("Invalid digit."); can be written as var t=document.getElementById("digit").value[0]/1;if(t!=t)return void alert("Invalid digit.");, which is the same but shorter. There are a few more things you can improve in it, but it does look great! Mar 3, 2015 at 15:08 • @IsmaelMiguel TBH I put it through a JS minifier to get it on one line. It was never meant to be golfed. Mar 3, 2015 at 15:16 • Oh, dude... That is a bit lazy... In a golfing question, you post a non-golfed code... But hey, I get it and I'm just saying this. You don't have to follow what I said. But it's a good thing to do. Mar 3, 2015 at 15:20 • @IsmaelMiguel I posted ungolfed utility code, which arguably should be as readable as possible so bugs are easier to spot. But really, as long as it works, the code size of the stack snippet has literally zero bearing on the outcome of the challenge. Mar 3, 2015 at 15:32 • text blocks may not be identical really? I want to see someone break this rule, by giving two identical codeblocks, which magically return different digits, when every number is exactly the same code ^^ Mar 4, 2015 at 10:39 6 Answers ><> (Fish), 5 * 10 = 50 Empty block  \ !9 4n; n/ 1n;\ \ 0n;n7\\\  Solid block  \; n8/ /!/!v \ ;6 3n;\ ! /nn 2n;n5< 8;  This code contains no logic or arithmetic only uses static redirections of ><>'s 2D instruction pointer (IP) with 'mirrors' (/ and \) and two 'arrows' (< and v). The only other flow-controller is the 'trampoline' (!) which jumps through the next character. The IP starts from the top left corner heading East. After some redirections it reaches a number it is pushed onto the stack and printed out with n and the program terminates with ;. The program flow A block 'recognizes' the current state of the program from the fact that which point the IP came in and based on the state it decides which direction should it to let out the pointer (which block should be executed next) and in which exact position the pointer should left (which will be the new state). Of course the blocks don't do any logic all this behavior comes from the redirectors. • I was hoping for an answer like this. Pure magic. Mar 4, 2015 at 10:59 CJam, 20181413 12 * 1 = 12 Try it online: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 Empty block ];BG*K+ :BD%  Solid block ];B9+33%:B4/  Explanation I used a similar strategy to Sp3000's solution, such that each block performs a multiplication, an addition, and (possibly) a modulo operation on a variable and saves the value back. To find an optimal solution, I used good old brute force. I wrote a program that searches the space of all possible initial values (the initial values of CJam variables) and many millions of possible pairs of transformation functions such that the output for every digit form is unique. Then, I filtered the results for ones such that the final result for digit forms ending in an empty block, of which there are 8, can be mapped back to the correct result via another multiply, add, and modulo formula. After a couple of days of CPU time of searching, the best result so far is down to a size of 12! This solution starts with a value of 11, the empty block transformation function is x * 16 + 20, the empty block result function is x % 13, the solid block transformation function is (x + 9) % 33, and the solid block result function is x / 4. CJam, 2322 19 * 1 = 19 Empty block: ];G)B%:G"73860594"=  Solid block: ];GW*B+3*D%:G 7-  I'm trying to get lucky with mathematical coincidences and failing, so here's a slightly different approach to uniqueness mapping from Martin's solution. Start with 16. Empty blocks add 1 and take modulo 11. Solid blocks multiply by -1, add 11, multiply by 3 then take modulo 13. This magically maps 03456789 (the digits which end on an empty block) to 41753026, which we use indexing to get right. 12 maps neatly to 89, which we can remedy by subtracting 7. CJam, 28 27 x 1 = 27 Here is a start. Empty block U):U;  Solid block ];U):UW+:WF%"1302986_7_54"=  Test it here. I can't give you a permalink with the code, because the code is too long, so you'll have to copy it in manually from the snippet in the challenge. The idea is to hash the shape as follows: • For each "pixel" increment a counter U. • For each black "pixel" add U to a running total W (which starts at -1). At the end, we take this modulo 15, which happens to give unique results, which use to index into a lookup string. Zsh-F, 1 * 34 = 34 Empty block: x+=0;X=5719060800034;(bye 2-x[2]);  Solid block: x+=1;(bye X[1+0b$x%13]);          

Outputs via exit code, which is the simplest way I could think of to get only the final block to output a value. bye exits with a status code, and () prevents the shell from actually exiting; it only sets the code, so the last value will be the exit code of the whole shell.

Each block also appends either 0 or 1 to a string x; If the last block is solid (only the case for 1 and 2), the output is 2 - (the second digit of x). If the last block is empty, then 0b$x converts x from binary, %13 takes it modulo thirteen, and then that is indexed into the string X which is initialised earlier, to choose the correct output code. Attempt This Online: 0 1 2 3 4 5 6 7 8 9 Here's the code for 5: x+=0;X=5719060800034;(bye 2-x[2]);x+=0;X=5719060800034;(bye 2-x[2]);x+=0;X=5719060800034;(bye 2-x[2]);x+=0;X=5719060800034;(bye 2-x[2]);x+=0;X=5719060800034;(bye 2-x[2]); x+=0;X=5719060800034;(bye 2-x[2]);x+=1;(bye X[1+0b$x%13]);          x+=1;(bye X[1+0b$x%13]); x+=1;(bye X[1+0b$x%13]);          x+=1;(bye X[1+0b$x%13]); x+=0;X=5719060800034;(bye 2-x[2]);x+=1;(bye X[1+0b$x%13]);          x+=1;(bye X[1+0b$x%13]); x+=1;(bye X[1+0b$x%13]);          x+=1;(bye X[1+0b$x%13]); x+=1;(bye X[1+0b$x%13]);          x+=0;X=5719060800034;(bye 2-x[2]);x+=0;X=5719060800034;(bye 2-x[2]);x+=0;X=5719060800034;(bye 2-x[2]);x+=1;(bye X[1+0b$x%13]); x+=1;(bye X[1+0b$x%13]);          x+=1;(bye X[1+0b$x%13]); x+=1;(bye X[1+0b$x%13]);          x+=1;(bye X[1+0b$x%13]); x+=0;X=5719060800034;(bye 2-x[2]); x+=0;X=5719060800034;(bye 2-x[2]);x+=1;(bye X[1+0b$x%13]);          x+=1;(bye X[1+0b$x%13]); x+=1;(bye X[1+0b$x%13]);          x+=0;X=5719060800034;(bye 2-x[2]);
x+=1;(bye X[1+0b$x%13]); x+=0;X=5719060800034;(bye 2-x[2]);x+=0;X=5719060800034;(bye 2-x[2]);x+=0;X=5719060800034;(bye 2-x[2]);x+=1;(bye X[1+0b$x%13]);


Each block, read left-to-right, constructs the string 00000011110111110001111100111010001, which is 519633361 in binary. This modulo 13 is 0, and then the 1+0'th character of X (5719060800034) is 5, so that's the exit code.

• Nice answer! I think this explanation's good enough for 300 rep, although giving an example for 0 or another digit wouldn't hurt.
– user
Jun 29, 2021 at 22:41

Python 3, 73 bytes

empty code:

a,b=id and(0,1)or(2*a+0,b+1);id=b>34and print(b'XH"V;G F@D'.index(a%91));


Try it online!

solid code:

a,b=id and(1,1)or(2*a+1,b+1);id=b>34and print(b'XH"V;G F@D'.index(a%91));


Try it online!

both code contains unprintable chars

How it works:

• on the first occurence of either empty or solid: as id is a python built-in, it is evaluated as True so id and <first> or <second> will evaluate <first> which initialise a and b. Then id is set to 0
• a is the binary representation of the code with 0 for empty and 1 for solid
• b is the number of bloc executed.
• when b is equal to 35 (last bloc) it prints the result.
• print(b'XH"V;G F@D'.index(a%91)) prints the index of the char whose codepoint is equal to a%91 (which is the right result)