7, 11 characters, 4 bytes
17370074023
Try it online!
Hexdump to prove byte count:
00000000: 3df0 3c09 =.<.
This challenge is very easy in most languages, so I decided to solve it in a language where it's actually an interesting problem.
Explanation
It took me ages to golf this down to 4 bytes – there are a really huge number of ways to do this with 12 characters, but reaching 11 is very difficult.
The only part of the code here that actually runs (after the first cycle, which just sets up the stack to mirror the structure of the program) is 4623
(which is the code generated by the code 4023
in the original program; the 4023
is a literal which pushes 4623
to the stack; as usual, I'm using non-bold for commands that just push code to the stack and bold for the commands they push). After the first cycle, each new cycle runs the top stack element, without actually popping it from the stack.
The 4
swaps the top two stack elements, and inserts a blank element between them (thus, a b goes to b blank a). Then the 6
analyzes the top element to determine what source code is most likely to have produced it, and appends the resulting source code to the element below it (which will be blank at this point because we just ran a 4
). Thus, the net effect of 46
is to swap the top two stack elements, and replace the top stack element with (a guess at, but the guesses are always correct for this program) the source code that produced it.
2
duplicates the top stack element, and 3
outputs the top stack element, popping both it and the element below. Thus, the net effect of 23
is to output and pop the top stack element, without disturbing elements below it.
As such, the effect of our program 4623
is to pop and output the source code that produced the second stack element, whilst leaving the top stack element unchanged. The top stack element in question is the actively running program (which doesn't get popped when we start to run it), so once the program finishes running, it'll just run again, etc. – this is in effect an infinite loop which, for each element on the stack, outputs the source code that produced it (and eventually the program crashes due to stack exhaustion). As such, the data being given to the output routines is 00
, 3
, 1
(i.e. the sections of the source code in between 7
s – the source code has already run to produce runnable code by this point, but the source is reconstructed from the runnable code rather than the runnable code actually being run).
The first 0
sent to the output routine selects numerical output mode. Then, 0
, 3
, 1
get output. The numerical value of a string in 7 is the total number of 1
and 7
characters it contains, minus the total number of 0
and 6
characters it contains. Thus, the values of these strings are -1, 0, and 1, as required by the question.
One complication is that if we try to output an empty string, we just get no output, rather than its numerical value of 0 being output: this is a special case needed because the output command 3
is the primary way to pop and discard stack elements (basically, you push an empty element above the one you want to pop, output that empty element and pop the element below as a side effect). A "clean" way to output 0 thus requires outputting a string like 01
which is nonempty and has a numerical value of zero. This program uses 3
, which is shorter, but the numerical output formatter will append a comma when outputting strings ending 3
(in addition to outputting their numerical value). As a consequence, the output of the program is actually -1 0, 1
, but this is permitted by the question. (All eight of the one-character strings either have a side effect when output via the numerical formatter, or else have a value different from zero, so outputting -1 0 1
exactly would make the program longer.)