:-:_
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 nada dependiendo del signo de la parte superior de la pila. Asi que...
*|]I*:*I[|*
Pruébalo en línea! El pie de página nuevamente incluye todas las otras alternativas en el mismo conteo de bytes. Algunas de esas salidas 1 / -1 y algunas salidas 2 / -2 como se indica después de cada programa. Elegí este para explicar un poco al azar como uno de los que producen 2.
¡Intenta lo contrario!
Explicación
Como dije, este es un poco más largo. Incluso si usáramos el-m
notation for this, it would weigh in at 6 bytes instead of the above 4.
Los comandos en uso esta vez:
* 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.
El primer programa solo usa dos pilas. Eso es un poco complicado de hacer en el arte ASCII, pero haré lo mejor que pueda. Los corchetes indican en qué pila está el cabezal de la cinta, y pondré los comandos entre cada par de estados de 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
… …
Ahora el -1
actúa como un marcador EOF y el2
se imprime.
El otro programa es el mismo hasta que [
. Sigue siendo prácticamente igual hasta el segundo I
. Técnicamente estaremos en una pila diferente, pero sin valores en ellos, todos son indistinguibles. Pero entonces la diferencia entre I[
y I]
termina importando:
*|[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
… … …
Y esta vez, no tenemos un marcador EOF, pero el programa aún genera el -2
.
-
(0x45 = 0b00101101) funciona en Jelly --
produce -1 ya que define el literal -1, mientras queṆ
(0xB4 = 0b10110100) produce 1 ya que realiza una lógica no de la entrada implícita de cero. (Por supuesto,Ṇ
funciona igual de bien: p)