Usa la tercera pila
Si ha leído el título, puede estar un poco confundido. ¿Seguramente solo hay dos pilas en Brain-Flak? Sin embargo, le aseguro que existe y que es una de las herramientas más poderosas, si no la más poderosa, para escribir y jugar Brain-Flak.
¿Qué es la "tercera pila"?
Cada programa Brain-Flak usa la tercera pila de una forma u otra, pero la mayor parte del uso se lleva a cabo detrás de escena y a menudo es útil simplemente ignorar el hecho de que existe. Cada paréntesis en el programa agrega o elimina un elemento de la pila. Tres de las llaves abiertas ([<
agregan un elemento a la pila, mientras que sus tres conjugados )]>
eliminan un elemento de la pila. El valor del elemento en la pila es el valor del alcance actual del programa y el uso de nilads modificará este valor de ciertas maneras. El paréntesis cerrado )
tiene la función única de mover un elemento de la tercera pila a la pila actual; un empujón.
Esperemos que esto te resulte claro. La tercera pila es una especie de pila que recuerda los valores de retorno del código que ya se ha ejecutado. Veamos un ejemplo de un programa simple que realiza un seguimiento de las dos pilas normales y la tercera pila.
Ejemplo
Recorreremos el siguiente programa. Este programa empuja -3, 1, -2
a la pila.
(([()()()])(()))
Comenzamos con tres llaves abiertas, que empujan un cero a la tercera pila.
Nuestras pilas ahora se ven así, la tercera pila es la de la derecha y la pila activa tiene ^
debajo:
0
0
0 0 0
^
(([()()()])(()))
^
Ahora tenemos tres ()
nilas. Estos no hacen nada a las dos pilas normales, sin embargo, cada una agrega una a la parte superior de la tercera pila haciendo que nuestras pilas se vean así:
3
0
0 0 0
^
(([()()()])(()))
^
Ahora encontramos que, ]
como se indicó antes, las llaves cerradas eliminan un elemento de la tercera pila, pero ]
tiene la función de restar el elemento que elimina de la parte superior de la pila. Así nuestras nuevas pilas se verán así:
-3
0 0 0
^
(([()()()])(()))
^
Esto tiene sentido; [...]
hace negación por lo que ]
debería restar hacia abajo.
Ahora debemos ejecutar a )
. Como probablemente recuerde, )
es el lugar en el programa donde las cosas se envían a la pila, por lo que moveremos la parte superior de la tercera pila a la pila actual, además agregaremos el -3
elemento siguiente en la tercera pila.
-3 0 -3
^
(([()()()])(()))
^
Una vez más nos encontramos con una de nuestras tres llaves abiertas, por lo que agregaremos otro elemento a nuestra tercera pila.
0
-3 0 -3
^
(([()()()])(()))
^
Como dijimos anteriormente, ()
aumentará la parte superior de nuestra tercera pila en uno.
1
-3 0 -3
^
(([()()()])(()))
^
Y )
moverá la parte superior de la tercera pila a la pila activa y agregará hacia abajo
1
-3 0 -2
^
(([()()()])(()))
^
El último )
mueve la tercera pila a la pila activa y, dado que no quedan elementos en la tercera pila para agregar, no hace nada más.
-2
1
-3 0
^
(([()()()])(()))
^
El programa ha terminado, así que terminamos y damos salida.
Este ejemplo tiene la intención de darle una idea de lo que es y hace el Third Stack. No incluye todas las operaciones, pero es de esperar que pueda descubrir qué hace cada una por sí solo. Si todavía tiene dificultades, he incluido una "hoja de trucos" en la parte inferior de esta respuesta para ayudarlo.
¿OK y eso qué?
Ok, ahora entiendes la tercera pila, pero "¿Y qué?" Ya lo estaba utilizando, incluso si no lo llamaba "Third Stack", ¿cómo le ayuda el golf en términos de Third Stack?
Veamos un problema. Desea tomar el triángulo de un número . Esta es la suma de todos los números menores que n.
Un enfoque podría ser crear un acumulador en la pila y agregarlo a medida que realiza la cuenta regresiva. Esto crea un código que se ve así:
(<>)<>{(({}[()])()<>{})<>}{}<>({}<>)
Pruébalo en línea!
Este código es bastante compacto y uno podría pensar que no puede ser mucho más pequeño. Sin embargo, si lo abordamos desde un punto de vista de la tercera pila, queda claro que esto es extremadamente ineficiente. En lugar de poner nuestro acumulador en la pila, podemos colocarlo en la tercera pila con un (
y recuperarlo al final que usamos )
. Una vez más, recorreremos todos los números, pero esta vez no tenemos que hacer nada para incrementar nuestra tercera pila, el programa lo hace por nosotros. Esto se ve así:
({()({}[()])}{})
Pruébalo en línea
Este código es menos de la mitad del tamaño de la versión bastante bien desarrollada que hicimos antes. De hecho, una búsqueda por computadora ha demostrado que este programa es el programa más corto posible que puede realizar esta tarea. Este programa se puede explicar utilizando el enfoque de "suma de todas las ejecuciones", pero creo que es mucho más intuitivo y claro cuando se explica utilizando un enfoque de Third Stack.
¿Cuándo uso la tercera pila?
Idealmente, cada vez que comience a trabajar en un nuevo problema en Brain-Flak, debe pensar cómo haría esto con la Tercera Pila en mente. Sin embargo, como regla general, siempre que tenga que realizar un seguimiento de algún tipo de acumulador o tenga un total acumulado, es una buena idea intentar colocarlo en su tercera pila en lugar de las dos pilas reales.
Otra vez que podría ser una buena idea considerar usar su tercera pila es cuando no tiene espacio para almacenar algún valor en las otras dos pilas. Esto puede ser particularmente útil cuando realiza manipulaciones en dos pilas existentes y desea guardar un valor para su uso posterior sin tener que realizar un seguimiento de dónde está.
Limitaciones de la tercera pila
El Third Stack es muy poderoso en muchos sentidos, pero viene con sus propias limitaciones e inconvenientes.
En primer lugar, la altura máxima de la pila para la tercera pila en cualquier punto determinado se determina en el momento de la compilación. Esto significa que si desea utilizar una cantidad de espacio en la pila, debe asignar ese espacio cuando está escribiendo el programa.
En segundo lugar, la tercera pila no es el acceso aleatorio. Esto significa que no puede realizar ninguna operación en ningún valor que no sea el valor más alto. Además, no puede mover valores en la pila (por ejemplo, intercambie los dos primeros elementos).
Conclusión
The Third Stack es una herramienta poderosa y lo consideraría esencial para todos los usuarios de Brain-Flak. Toma un tiempo acostumbrarse y requiere un cambio en la forma en que piensas sobre la programación en Brain-Flak, pero cuando se usa correctamente, hace toda la diferencia entre un juego decente y uno increíble cuando se trata de jugar al golf.
Hoja de trucos
Aquí hay una lista de operaciones y cómo afectan la tercera pila
Operation | Action
====================================================
(,[,< | Put a zero on top of the Third Stack
----------------------------------------------------
) | Add the top of the Third Stack to the
| second element and move it to the
| active stack
----------------------------------------------------
] | Subtract the top of the Third Stack
| from the second element and pop it
----------------------------------------------------
> | Pop the top of the Third Stack
----------------------------------------------------
() | Add one to the top of the Third Stack
----------------------------------------------------
{} | Pop the top of the active stack and
| add it to the top of the Third Stack
----------------------------------------------------
[] | Add the stack height to the Third
| Stack
----------------------------------------------------
<>,{,} | Nothing