7, 29 bytes, 78 characters
Not going to win, but I had fun writing it. 7 uses a 3-bit character set that packs 8 characters into 3 bytes. Here's the program in octal encoding (which is most natural for the language):
770267133177162277266362217240522405240540562240540554240524052405052405405513
and here's how it looks on disk (via an xxd
dump); looking on the right, we can verify that the file contains no digits:
00000000: fc2d cb67 f392 fd6c f247 a82a 5055 0582 .-.g...l.G.*PU..
00000010: e4a0 b05b 1415 4154 1455 0582 d2 ...[..AT.U...
Try it online!
Underload is the brainfuck of stack-based languages, and 7 is a variant of Underload modified to provide I/O capabilities and to reduce the size of the command set. (The command set had to be modified to allow for things like outputting mismatched parentheses.) So this is an example of how to write this program in a very primitive and low-level language.
Here's how the program works:
77026
We start by pushing the stack element 02
, escaped once (thus it'll still appear as 02
on the stack; normally there's one level of unescaping). To push a stack element in 7, you precede it with a 7
, and enclose any parts you want to escape in 7
…6
.
7 133 17 716 22 77266 36
( ( ) (( )) )
The rest of the program is all stored in one large stack element. (In 7, there's no way to write code that runs immediately; you have to start by pushing it as a literal to the stack, then rely on it getting appended to the program implicitly when the program runs out of space.) We start by discarding the large stack element in question (13
), then outputting the element below (3
); that's 02
. The first output of the program sets the output format the program uses. In this case, we're using output format 0, "integers". That accounts for (and removes) the zero. The output format we're using works by counting the number of 7s and 1s in the output string, and subtracting the number of 6s and 0s, to produce the integer to output; in this case, the string 2
has no 0s, 1s, 6s, or 7s, so it outputs 0
. Finally, a trailing 2 (in this output format) produces a newline (the output would "naturally" be space-separated). After that, we push a large literal to the stack. This will eventually be used as a loop body, so we'll consider it when it runs.
22 1724052240524054056 2240540554240524052405052405405
Some people here may be used to Underload numerals from a previous challenge. 7 numerals are fairly similar. In the linked challenge, the only characters used were :
and *
; numbers represented like that can translate into 7 directly, with 2
serving the role of :
and 405
serving the role of *
(note that it's actually equivalent to Underload's ~*
, but the two act identically in this context). Thus, given a number n, you can add 1 to it using 2n405
, and you can multiply two numbers by appending them to each other; the null string is 1. One thing the linked challenge didn't mention, though, is exponentiation. This works a little differently in 7 than in Underload, but the same basic principles are in use in each case. Additionally, in 7, you can handle addition via putting code between the 4
and 05
(something that's more verbose in Underload because you can't put code inside the *
). So we can restructure this part of the program like this:
2
2
17 start a new number (=1)
2405 ×2 (=2)
2 ×(1 (=1)
2405 ×2 (=2)
2405 ×2 (=4)
405 +1 (=5)) (=10)
6 end of the new number
2 ×(1 (=1)
2405 ×2 (=2)
405 +1 (=3)) (=3)
5 exponentiate (10 ^ 3 = 1000)
4 +(1 (=1)
2405 ×2 (=2)
2405 ×2 (=4)
2405 ×2 (=8)
05 ) (=1008)
2405 ×2 (=2016)
405 +1 (=2017)
The rest of the program is:
5 13
The 5
starts a loop, running the stack literal we pushed earlier 2017 times. Finally, the 13
pops the top stack element, meaning that the stack is now empty and the program ends.
So what does the loop body do? Here's how it decodes:
716 Append a 1 to TOS
22 Make two more copies of the TOS
77266 Append a 2 to TOS
3 Output TOS, discard top two stack elements
Appending a 1 will increase the numerical value (initially zero) that numeric output will see the stack as having. We make two temporary copies, and append a 2 (to provide the newline required by the question). Then we output it, discarding the temporary copies in the process. Doing this 2017 times will thus count from 1 to 2017. We outputted the 0 earlier, thus completing the program.
This is rather vague. How should the numbers be printed? What constitutes an external variable? You give two examples but never define it. What constitutes a valid token? – Conor O'Brien – 2016-12-12T21:57:23.133
@ConorO'Brien please read the linked post. – cascading-style – 2016-12-12T21:58:05.710
3Questions should be self-contained. You need to specify these in your own post, should the old question be unavailable in the future. – Conor O'Brien – 2016-12-12T21:58:46.543
@ConorO'Brien Ok, i am editing it now. – cascading-style – 2016-12-12T21:59:24.667
What is so wrong with my question? please let me know so that I can fix it.@Dennis @ConnorO'Brien – cascading-style – 2016-12-12T22:13:40.890
For starters, you still haven't ruled which output formats are acceptable. Do we have to print then numbers separated by newlines? Can we return a list of numbers from a function? – Dennis – 2016-12-12T22:16:40.233
That said, even with a perfect specification, it might still be considered a duplicate of the previous challenge. The difference is that we cannot simply print 20 and 17 this time; it has to be a single integer. – Dennis – 2016-12-12T22:20:47.770
14
Don't be tricked the printing 2014 challenge having masses of votes. By modern standards, it's pretty awful, and I'd expect it to get a poor reception if posted today. See Using old challenges as a model as a thing to avoid, as well as Do X without Y.
– xnor – 2016-12-12T22:21:27.1201^ Agreed. Come up with your own unique challenge. – mbomb007 – 2016-12-12T22:32:28.793
1Too bad this was closed. I just came up with a 7 char/8 byte solution. – Adám – 2016-12-13T10:49:17.787
2By the way, you also posted this (and suggested an edit to my 2014 question) about 19 days too early. The New Year's Puzzle is supposed to be posted exactly on the new year, wherever it happens to be where you live. – Joe Z. – 2016-12-13T16:40:34.417
1Also, I think you just accepted my answer too quickly. I'd suggest waiting at least 7 days :) – Erik the Outgolfer – 2016-12-15T15:46:21.960
In order to enter, I have to use line numbers for the Sinclair ZX81 - even if I write it in assembly. Will this still be allowed? – Shaun Bebbers – 2017-04-04T07:05:07.957