:-:_
Try it online! In the footer I've included all other 4-byte solutions. (Stack Cats ignores everything after the first linefeed.)
Try the reverse!
Explanation
The -n
flag turns on numeric output (and input, but we don't have any), and the -m
flag is normally just a golfing convenience which lets you avoid the redundant part of the source code. This is because every Stack Cats program needs to have mirror symmetry. With the -m
flag you only give it the first half (plus the central character). So the actual program here is:
:-:_:-:
As you can see in the first TIO link, there's a ton of 4-byte solutions, but I picked this one for its simplicity. Stack Cats is stack-based, and this program only uses the initial stack. Since we don't have any input, it contains a single -1
(an EOF marker) on top of an infinite well of zeros. The three commands in the program have the following meaning:
: Swap the top two stack elements.
- Negate the top stack element (i.e. multiply by -1).
_ Pop a. Peek b. Push b-a.
So here is how the program modifies the stack (states and commands are staggered to indicate how each command changes the stack from one state to the next):
: - : _ : - :
-1 0 0 -1 1 0 0 1
0 -1 -1 0 0 1 1 0
0 0 0 0 0 0 0 0
… … … … … … … …
As it turns out, the only command that really does anything here is _
which turns our EOF marker into a 1
. Output at the end of the program is implicit, and the EOF marker is optional, so this just prints out the 1
we get.
Now if we reverse the source code, due to the implicit mirroring, the actual program becomes:
_:-:-:_
This does something very different:
_ : - : - : _
-1 1 0 0 1 -1 0 -1
0 0 1 1 0 0 -1 -1
0 0 0 0 0 0 0 0
… … … … … … … …
This time the bottom of the stack is still a -1
so it does act as the EOF marker and only the -1
on top of it gets printed.
...
Now with all of that said, since Stack Cats has such a unique relationship with reversing code, I feel that using -m
is a little cheating. It's normally only meant to save bytes by omitting the redundant part of the source code, but here it actually makes the challenge a lot easier and even the full program shorter. This is because reversing a full program will only change the program if it contains any of <>[]
, which also means that the program ends up making use of multiple stacks (Stack Cats actually has a tape of stacks, where all but the initial one are only filled with zeros to begin with). Furthermore, reversing it then just swaps the <>
and []
pairs, which still makes the execution symmetric. The only way to break that symmetry is to use I
which does -]
or -[
o niente a seconda del segno della parte superiore della pila. Così...
*|]I*:*I[|*
Provalo online! Il piè di pagina include di nuovo tutte le altre alternative con lo stesso numero di byte. Alcuni di questi producono 1 / -1 e altri 2 / -2 come indicato dopo ciascun programma. Ho scelto questo per spiegarlo in modo casuale come uno di quelli che hanno prodotto 2.
Prova il contrario!
Spiegazione
Come ho già detto, questo è un po 'più lungo. Anche se abbiamo usato il-m
notation for this, it would weigh in at 6 bytes instead of the above 4.
I comandi in uso questa volta:
* Toggle the least significant bit of the top of the stack.
| Reverse the longest non-zero of prefix on this stack.
[] Move one stack to the left/right and take the top of the current stack with you.
I If the top of the stack is positive, -], if it's negative, -[, otherwise do nothing.
: Swap the top two stack elements.
Il primo programma utilizza solo due pile. È un po 'complicato da fare nell'arte ASCII, ma farò del mio meglio. Le parentesi quadre indicano su quale pila si trova la testina e inserirò i comandi tra ciascuna coppia di stati di pila.
[-1]
… 0 0 …
0 0
… …
*
[-2]
… 0 0 …
0 0
… …
| (does nothing)
]
[-2]
… 0 0 …
0 0
… …
I
[2]
… 0 0 …
0 0
… …
*
[3]
… 0 0 …
0 0
… …
:
[0]
… 3 0 …
0 0
… …
*
[1]
… 3 0 …
0 0
… …
I
[-1]
… 3 0 …
0 0
… …
[
[-1]
… 3 0 …
0 0
… …
|
[ 3]
… -1 0 …
0 0
… …
*
[ 2]
… -1 0 …
0 0
… …
Ora -1
agisce come un marker EOF e il2
viene stampato.
L'altro programma è lo stesso fino a quando [
. È ancora praticamente lo stesso fino al secondo I
. Saremo tecnicamente su uno stack diverso, ma senza valori su di essi, sono tutti indistinguibili. Ma poi la differenza tra I[
e I]
finisce per essere importante:
*|[I*:*I
[-1]
… 3 0 0 …
0 0 0
… … …
]
[-1]
… 3 0 0 …
0 0 0
… … …
| (does nothing)
*
[-2]
… 3 0 0 …
0 0 0
… … …
E questa volta, non abbiamo un marker EOF, ma il programma continua a produrre -2
.
-
(0x45 = 0b00101101) funziona in Jelly --
produce -1 poiché definisce il letterale -1, mentreṆ
(0xB4 = 0b10110100) produce 1 poiché esegue un logico non dell'input implicito di zero. (NaturalmenteṆ
funziona altrettanto bene: p)