Use a terceira pilha
Se você leu o título, pode ficar um pouco confuso. Certamente existem apenas duas pilhas no Brain-Flak? No entanto, garanto que ele existe e é uma das ferramentas mais poderosas, se não a mais poderosa, para escrever e jogar no Brain-Flak.
O que é o "Third Stack"?
Todo programa Brain-Flak usa a terceira pilha de uma maneira ou de outra, mas a maior parte do uso é realizada nos bastidores e geralmente é útil simplesmente ignorar o fato de que ela existe. Cada parêntese no programa adiciona ou remove um item da pilha. Três dos chavetas abertos ([<
adicionam um item à pilha, enquanto os três conjugados )]>
removem um item da pilha. O valor do item na pilha é o valor do escopo atual do programa e o uso de nilads modificará esse valor de determinadas maneiras. O parêntese próximo )
tem a função exclusiva de mover um elemento da Terceira Pilha para a pilha atual; um empurrão.
Espero que isso esteja ficando claro para você. A Terceira Pilha é algum tipo de pilha que lembra os valores de retorno do código que já foi executado. Vamos seguir um exemplo de um programa simples, acompanhando as duas pilhas normais e a Terceira Pilha.
Exemplo
Seguiremos o seguinte programa. Este programa envia -3, 1, -2
para a pilha.
(([()()()])(()))
Começamos com três chaves abertas, que empurram o zero para a terceira pilha.
Nossas pilhas agora se parecem com isso, a Terceira Pilha é a da direita e a pilha ativa tem uma parte ^
inferior:
0
0
0 0 0
^
(([()()()])(()))
^
Agora temos três ()
niladas. Isso não faz nada com as duas pilhas normais, no entanto, cada uma adiciona uma ao topo da Terceira Pilha, fazendo com que nossas pilhas se pareçam com:
3
0
0 0 0
^
(([()()()])(()))
^
Agora encontramos um, ]
conforme declarado antes, que chaves fechadas removem um item da Terceira Pilha, mas ]
tem a função de subtrair o elemento que ele remove da parte superior da pilha. Assim, nossas novas pilhas terão a seguinte aparência:
-3
0 0 0
^
(([()()()])(()))
^
Isso faz sentido; [...]
negação ]
deve subtrair para baixo.
Agora devemos executar a )
. Como você provavelmente se lembra, )
é o local do programa em que as coisas são empurradas para a pilha, de modo que moveremos o topo da Terceira Pilha para a pilha atual, além disso, adicionaremos o -3
elemento ao próximo na terceira pilha.
-3 0 -3
^
(([()()()])(()))
^
Mais uma vez encontramos um de nossos três chavetas abertas, para adicionar outro elemento à nossa Terceira Pilha.
0
-3 0 -3
^
(([()()()])(()))
^
Como dissemos anteriormente ()
, aumentará o topo da nossa terceira pilha em um.
1
-3 0 -3
^
(([()()()])(()))
^
E )
moverá o topo da Terceira Pilha para a pilha ativa e adicionará para baixo
1
-3 0 -2
^
(([()()()])(()))
^
O último )
move a Terceira Pilha para a pilha ativa e, como não há elementos restantes na Terceira Pilha para adicionar, não faz mais nada.
-2
1
-3 0
^
(([()()()])(()))
^
O programa terminou, então finalizamos e produzimos.
Este exemplo tem como objetivo dar uma idéia do que a Terceira Pilha é e faz. Ele não inclui todas as operações, mas espero que você possa descobrir o que cada uma delas faz por conta própria. Se você ainda está com dificuldades, incluí uma "folha de dicas" na parte inferior desta resposta para ajudá-lo.
Tá, e daí?
Ok, agora você entende a Terceira Pilha, mas "E daí?" Você já o estava usando, mesmo que não o chamasse de "Terceiro Stack", como o pensamento em termos do Third Stack o ajuda a jogar golfe?
Vamos olhar para um problema. Você quer pegar o triângulo de um número . Esta é a soma de todos os números menores que n.
Uma abordagem pode ser criar um acumulador no offstack e adicioná-lo à medida que você faz a contagem regressiva. Isso cria um código que se parece com isso:
(<>)<>{(({}[()])()<>{})<>}{}<>({}<>)
Experimente Online!
Este código é bastante compacto e pode-se pensar que não pode ficar muito menor. No entanto, se o abordarmos do terceiro ponto de vista da pilha, fica claro que isso é grosseiramente ineficiente. Em vez de colocar nosso acumulador na pilha, podemos colocá-lo na terceira pilha com um (
e recuperá-lo no final que usamos )
. Mais uma vez, percorreremos todos os números, mas desta vez não precisamos fazer muito para incrementar nossa Terceira Pilha, o programa faz isso por nós. Isso se parece com:
({()({}[()])}{})
Experimente Online
Esse código tem menos da metade do tamanho da versão bastante bem elaborada que fizemos anteriormente. De fato, uma pesquisa no computador comprovou que esse programa é o programa mais curto possível que pode executar essa tarefa. Este programa pode ser explicado usando a abordagem "soma de todas as execuções", mas acho que é muito mais intuitivo e claro quando explicado usando uma abordagem da Terceira Pilha.
Quando uso a Terceira Pilha?
Idealmente, sempre que você começar a trabalhar em um novo problema no Brain-Flak, pense em como eu faria isso com a Terceira Pilha em mente. No entanto, como regra geral, sempre que você tiver que rastrear algum tipo de acumulador ou ter um total em execução, é uma boa ideia tentar colocá-lo na sua terceira pilha, em vez das duas pilhas reais.
Outro momento em que pode ser uma boa ideia considerar o uso da terceira pilha é quando você não tem espaço para armazenar algum valor nas outras duas pilhas. Isso pode ser particularmente útil quando você está fazendo manipulações em duas pilhas existentes e deseja salvar um valor para uso posterior sem precisar acompanhar onde está.
Limitações da terceira pilha
O Third Stack é muito poderoso de várias maneiras, mas vem com suas próprias limitações e desvantagens.
Em primeiro lugar, a altura máxima da pilha para a terceira pilha em qualquer ponto é determinada em tempo de compilação. Isso significa que, se você quiser usar uma quantidade de espaço na pilha, precisará alocar esse espaço ao escrever o programa.
Em segundo lugar, a terceira pilha não é de acesso aleatório. Isso significa que você não pode executar nenhuma operação com nenhum valor, exceto o valor mais alto. Além disso, você não pode mover valores na pilha (por exemplo, troque os dois primeiros elementos).
Conclusão
O Third Stack é uma ferramenta poderosa e eu consideraria essencial para todos os usuários do Brain-Flak. Demora um pouco para se acostumar e requer uma mudança na maneira como você pensa sobre programação no Brain-Flak, mas quando usado corretamente, faz toda a diferença entre um decente e um incrível quando se trata de golfe.
Folha de dicas
Aqui está uma lista de operações e como elas afetam a Terceira Pilha
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