Utilisez la troisième pile
Si vous avez lu le titre, vous pourriez être un peu confus. Il n'y a sûrement que deux piles dans Brain-Flak? Cependant, je vous assure qu'il existe et qu'il est l'un des outils les plus puissants sinon le plus puissant pour écrire et jouer au Brain-Flak.
Qu'est-ce que la "troisième pile"?
Chaque programme Brain-Flak utilise la troisième pile d'une manière ou d'une autre, mais la majeure partie de l'utilisation se déroule en arrière-plan et il est souvent utile d'ignorer simplement le fait qu'elle existe. Chaque parenthèse du programme ajoute ou supprime un élément de la pile. Trois des accolades ouvertes ([<
ajoutent toutes un élément à la pile tandis que leurs trois conjugués )]>
retirent tous un élément de la pile. La valeur de l'élément sur la pile est la valeur de la portée actuelle du programme et l'utilisation de nilads modifiera cette valeur de certaines manières. La parenthèse fermée )
a la fonction unique de déplacer un élément de la troisième pile vers la pile actuelle; une poussée.
J'espère que cela devient clair pour vous. La troisième pile est une sorte de pile qui se souvient des valeurs de retour du code qui a déjà été exécuté. Passons en revue un exemple de programme simple gardant une trace des deux piles normales et de la troisième pile.
Exemple
Nous allons parcourir le programme suivant. Ce programme pousse -3, 1, -2
vers la pile.
(([()()()])(()))
Nous commençons avec trois accolades ouvertes, qui poussent toutes un zéro vers la troisième pile.
Nos piles ressemblent maintenant à ceci, la troisième pile est celle de droite et la pile active a un ^
dessous:
0
0
0 0 0
^
(([()()()])(()))
^
Maintenant, nous avons trois ()
nilades. Celles-ci ne font rien aux deux piles normales, mais elles en ajoutent chacune une en haut de la troisième pile, ce qui donne à nos piles l'apparence suivante:
3
0
0 0 0
^
(([()()()])(()))
^
Maintenant, nous rencontrons un ]
comme indiqué avant les accolades proches retirent un élément de la troisième pile, mais ]
a la fonction de soustraire l'élément qu'il supprime du haut de la pile. Ainsi, nos nouvelles piles ressembleront à:
-3
0 0 0
^
(([()()()])(()))
^
C'est logique; [...]
fait la négation ]
devrait donc soustraire vers le bas.
Nous devons maintenant exécuter a )
. Comme vous vous en souvenez probablement, )
c'est l'endroit dans le programme où les choses sont poussées vers la pile, donc nous déplacerons le haut de la troisième pile vers la pile actuelle, en plus nous ajouterons l' -3
élément suivant à l'élément dans la troisième pile.
-3 0 -3
^
(([()()()])(()))
^
Une fois de plus, nous rencontrons l'un de nos trois accolades ouvertes, nous allons donc ajouter un autre élément à notre troisième pile.
0
-3 0 -3
^
(([()()()])(()))
^
Comme nous l'avons dit plus tôt, ()
nous incrémenterons le haut de notre troisième pile d'une unité.
1
-3 0 -3
^
(([()()()])(()))
^
Et )
déplacera le haut de la troisième pile sur la pile active et ajoutera vers le bas
1
-3 0 -2
^
(([()()()])(()))
^
Le dernier )
déplace la troisième pile sur la pile active et comme il n'y a plus d'éléments à ajouter sur la troisième pile, ne fait rien d'autre.
-2
1
-3 0
^
(([()()()])(()))
^
Le programme est terminé donc nous terminons et sortons.
Cet exemple est destiné à vous donner une idée de ce qu'est et fait la troisième pile. Il n'inclut pas toutes les opérations, mais j'espère que vous pourrez comprendre ce que chacune fait d'elle-même. Si vous avez encore du mal, j'ai inclus une "feuille de triche" au bas de cette réponse pour vous aider.
Okay, alors quoi?
Ok, maintenant vous comprenez la troisième pile, mais "Et alors"? Vous l'utilisiez déjà, même si vous ne l'appeliez pas "Third Stack", comment la pensée en termes de Third Stack vous aide-t-elle à jouer au golf?
Regardons un problème. Vous voulez prendre le triangle d'un nombre . Il s'agit de la somme de tous les nombres inférieurs à n.
Une approche pourrait consister à créer un accumulateur sur la pile et à y ajouter au fur et à mesure que vous comptez à rebours. Cela crée du code qui ressemble à ceci:
(<>)<>{(({}[()])()<>{})<>}{}<>({}<>)
Essayez-le en ligne!
Ce code est assez compact et on pourrait penser qu'il ne peut pas devenir beaucoup plus petit. Cependant, si nous l'abordons d'un troisième point de vue de la pile, il devient clair que cela est extrêmement inefficace. Au lieu de mettre notre accumulateur sur la offstack, nous pouvons le mettre sur la troisième pile avec un (
et le récupérer à la fin que nous utilisons )
. Nous allons à nouveau parcourir tous les chiffres, mais cette fois, nous n'avons pas grand-chose à faire pour augmenter notre troisième pile, le programme le fait pour nous. Cela ressemble à ceci:
({()({}[()])}{})
Essayez-le en ligne
Ce code est moins de la moitié de la taille de la version assez bien golfée que nous avons faite auparavant. En fait, une recherche informatique a prouvé que ce programme est le programme le plus court possible pouvant effectuer cette tâche. Ce programme peut être expliqué en utilisant l'approche "somme de tous les runs", mais je pense qu'il est beaucoup plus intuitif et clair lorsqu'il est expliqué en utilisant une approche Third Stack.
Quand dois-je utiliser la troisième pile?
Idéalement, chaque fois que vous commencez à travailler sur un nouveau problème dans Brain-Flak, vous devriez penser à vous-même comment pourrais-je faire cela avec la troisième pile à l'esprit. Cependant, en règle générale, chaque fois que vous devez suivre un certain type d'accumulateur ou avoir un total cumulé, c'est une bonne idée d'essayer de le mettre sur votre troisième pile au lieu des deux vraies piles.
Une autre fois où cela peut être une bonne idée d'envisager d'utiliser votre troisième pile, c'est quand vous n'avez pas d'espace pour stocker de la valeur sur les deux autres piles. Cela peut être particulièrement utile lorsque vous effectuez des manipulations sur deux piles existantes et que vous souhaitez enregistrer une valeur pour une utilisation ultérieure sans avoir à suivre où elle se trouve.
Limitations de la troisième pile
La troisième pile est très puissante à bien des égards, mais elle a ses propres limites et inconvénients.
Premièrement, la hauteur de pile maximale pour la troisième pile à tout moment donné est déterminée au moment de la compilation. Cela signifie que si vous souhaitez utiliser une quantité d'espace sur la pile, vous devez allouer cet espace lorsque vous écrivez le programme.
Deuxièmement, la troisième pile n'est pas un accès aléatoire. Cela signifie que vous ne pouvez effectuer aucune opération sur une valeur autre que la valeur la plus élevée. De plus, vous ne pouvez pas déplacer les valeurs sur la pile (disons permuter les deux premiers éléments).
Conclusion
La troisième pile est un outil puissant et je considère qu'elle est essentielle pour chaque utilisateur de Brain-Flak. Il faut un certain temps pour s'y habituer et nécessite un changement dans votre façon de penser à la programmation dans Brain-Flak, mais lorsqu'il est utilisé correctement, il fait toute la différence entre un décent et un incroyable en matière de golf.
Cheatsheet
Voici une liste des opérations et comment elles affectent la troisième pile
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