Le troisième Flak!

19

Ce défi a été publié dans le cadre du défi LotM d'avril 2018


Brain-Flak est un langage turing-tarpit qui a acquis beaucoup de renommée ici sur PPCG. La mémoire de la langue est composée de deux piles, mais un « caché » troisième pile a été découverte par Wh e à Wizard , conduisant à de nouvelles façons intéressantes de penser les programmes Brain-Flak.

Alors, qu'en est-il de donner plus de visibilité à cette pauvre troisième pile cachée? Créons un langage où la troisième pile a la reconnaissance qu'elle mérite! Ici, je vous présente Third-Flak .

La langue

Dans Third-Flak, il n'y a qu'une seule pile, appelée la troisième pile. Les opérateurs travaillent sur la troisième pile de la même façon que dans Brain-Flak, mais ici il n'y a pas [], {}, <>nilads et pas {...}monade ( de sorte que les caractères ne sont recevables que dans un programme de troisième Flak sont ()[]<>). Voici ce que fait chaque opérateur (des exemples seront donnés représentant la troisième pile avec une liste où le dernier élément est le haut de la pile):

  • ()est le seul opérateur à deux caractères de Third-Flak. Il augmente le haut de la troisième pile de 1. Exemple: [1,2,3][1,2,4]

  • (, [, <: Toutes les parenthèses d'ouverture qui ne sont pas couverts par le cas précédent pousser un 0à la troisième pile. Exemple: [1,2,3][1,2,3,0]

  • )sort deux éléments de la troisième pile et repousse leur somme. Exemple: [1,2,3][1,5]

  • ]sort deux éléments de la troisième pile et repousse le résultat de la soustraction du premier de la seconde. Exemple: [1,2,3][1,-1]

  • >sort un élément de la troisième pile. Exemple [1,2,3][1,2]

Et voici les autres règles de la langue:

  • Au début de l'exécution, la troisième pile ne contient qu'un seul 0.

  • Il est interdit d'avoir vide []ou à l' <>intérieur d'un programme (ils seraient de toute façon noops s'ils suivaient la sémantique de Third-Flak, mais ils ont en fait une signification différente dans Brain-Flak qu'il n'est pas possible de recréer ici).

  • Les parenthèses doivent toujours être équilibrées, à l'exception du fait que les parenthèses fermantes de fin à la fin du programme peuvent être manquantes. Par exemple, [()<(()est un programme Third-Flak valide (et la troisième pile à la fin du programme serait [1,0,1]).

  • Un programme ne peut contenir que les six caractères autorisés ()[]<>. Les programmes sont garantis non vides.

Remarque: il est sous-entendu par les règles précédentes que vous n'aurez pas à faire face à des situations où vous devez sauter d'une pile vide.

Le défi

Simple, écrivez un interprète pour Third-Flak. Votre programme doit prendre en entrée un programme Third-Flak et retourner en sortie l'état de la troisième pile à la fin du programme.

Votre format de sortie est flexible tant qu'il est possible de lire sans ambiguïté l'état de la troisième pile et le même nombre est toujours codé de la même manière (c'est juste une façon de dire que tout format de sortie qui n'est pas flagrant) essayer de tricher est très bien).

Votre choix de sortie peut restreindre la plage de nombres que vous pouvez gérer tant que cela ne banalise pas le défi (car ce serait une faille par défaut ).

Cas de test

Pour chaque scénario de test, la première ligne est l'entrée et la deuxième ligne la pile de sortie représentée sous la forme d'une liste de nombres séparés par des espaces où le haut de la pile est le dernier élément.

[()<(()
0 1 0 1

[((((()()()()()))
0 0 0 5

((([()][()][()])))
-3

[<<(((()()()())(((((
0 0 0 0 0 4 0 0 0 0 0

[()]<(([()])><[()]
-1 0 -1

(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(())(())(()())(())(())(())(()())(()()()())(())(()()()()())(()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(())(())(()())(())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(())(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(()()())(())(()()())(())(())(())(()())(()()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(())(())(())(()()())(())(())(())(()())(())(()())(()()()())(())(())(()()()()())(()())(()())(())(()()())(())(())(())(())(()()())(()())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(()()()()())(())(()()())(())(())(()())(())(()()()()())(())(()()()()())(())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()()()())(())(()()()()())(())(())(())(()())(())(()()()()())(())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()()()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(())(()())(()()()())(())(())(()())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(()()())(())(())(()())(())(())(()()()()())(()()()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(()()()())(()()()())(()()
718 2
Leo
la source
La pile est-elle initialisée avec un 0? Sinon, [()]enfreint la règle selon laquelle nous n'avons pas à nous soucier de sauter d'une pile vide
Jo King
1
@JoKing Yep: "Au début de l'exécution, la troisième pile ne contient qu'un seul 0". Je devrais peut-être souligner un peu cette partie, je craignais qu'elle aurait été trop facile à manquer.
Leo
Oups, je ne sais pas comment j'ai raté ça
Jo King
7
Barré e est toujours e.
Wheat Wizard
2
Si quelqu'un ne peut pas voir cela, le barré eest ici .
user202729

Réponses:

21

Brain-Flak , 276 octets

{({}<>)<>}<>{(((()()()()()){})((({}){})())(({})({}{}([{}])(<>))))((()()(){[()]<{}>}{}){()<{{}}>}{}<<>({}({})())>{()(<{}>)}{}<>)<>}<>{(([{}]()<>)){{}({}())((){[()](<({}())((){[()](<({}())((){[()](<{}([{}]{})>)}{}){(<{}{}>)}{}>)}{}){(<{}({}{})>)}{}>)}{}){(<{}{}({}())>)}}{}<>}<>

Essayez-le en ligne!

Vous deviez savoir que cela allait arriver.

Nitrodon
la source
4

Retina 0.8.2 , 64 48 46 octets

\(\)
_
[([<]
¶
+1`¶(.*)\)|(.*)¶\2]|¶.*>
$1
%`_

Essayez-le en ligne! Sort la pile de bas en haut. Fonctionne uniquement avec des entiers non négatifs, et le dernier scénario de test est trop lent, donc le lien ne comprend que trois scénarios de test. Explication: la pile précède implicitement le programme, elle commence donc comme la chaîne vide, qui représente un seul zéro. Le ()nilad est transformé en un _qui est utilisé pour compter en unaire, tandis que les autres supports ouverts sont transformés en sauts de ligne qui poussent un zéro sur la pile au fur et à mesure qu'ils sont rencontrés. Les parenthèses fermées sont ensuite traitées une à la fois afin que la pile soit correcte; le )supprime la nouvelle ligne précédente, en ajoutant les deux premiers éléments ensemble, le ]supprime l'élément supérieur et le fait correspondre à l'élément précédent sur la pile, le soustrayant ainsi, et le>supprime simplement l'élément supérieur. Enfin, la pile est convertie en décimal. Edit: sauvé 2 octets grâce à @Leo.

Neil
la source
À quoi ça $3sert? (bonne réponse quand même!)
Leo
@Leo C'est un reste d'un golf précédent. Merci de l'avoir repéré!
Neil
4

Python 3 , 145 144 132 132 122 116 109 104 104 octets

-7 octets grâce à Leo!

Et - 5 merci à Lynn!

s=[0]
for i in input().replace('()',' '):s+=i in']>) 'and(i<'!'or(2-ord(i)%5)*s.pop())+s.pop(),
print(s)

Essayez-le en ligne!

Implémentation assez standard. Pas si lisible maintenant cependant. Je suis déçu de ne pas avoir pu trouver un moyen plus court de vérifier entre les crochets de début et de fin.

Quelques tentatives de one-liners:

  • 124 octets (fonction anonyme):

    lambda c:[s.append(i in']>) 'and(i<'!'or~-']>)'.index(i)*s.pop())+s.pop())or s for s in[[0]]for i in c.replace('()',' ')][0]
  • 115 octets (programme complet):

    s=[0];[s.append(i in']>) 'and(i<'!'or~-']>)'.index(i)*s.pop())+s.pop())for i in input().replace('()',' ')];print(s)

L'ajout est énormément plus long que la simple affectation

Jo King
la source
~-']>)'.index(i)peut être (2-ord(i)%5)d'économiser 4 octets.
Lynn
2

Rubis , 98 91 octets

->s{a=[i=0];s.chars{|c|a<<("([<"[c]?s[i,2]["()"]?1:0:a.pop*~-"]>)".index(c)+a.pop);i+=1};a}

Essayez-le en ligne!

Mon code initial fonctionnait de manière similaire dans l'esprit à la réponse Python de Jo King, de sorte qu'avant de parcourir les caractères source, nous avons remplacé toutes les ()sous-chaînes par un autre caractère, en tant qu'opérateur distinct.

Cependant, au moins dans Ruby, il s'est avéré que le golfeur ne faisait pas cela, mais optait plutôt pour une approche légèrement plus lourde. Ici, nous maintenons un indexeur supplémentaire en igardant une trace de notre position dans la chaîne source, et chaque fois qu'un crochet d'ouverture est rencontré, nous vérifions en amont si nos caractères actuels + suivants s[i,2]forment l' ()opérateur. Dans ce cas, nous poussons 1 au lieu de 0 en haut de la pile et laissons la fermeture )faire son travail à l'étape suivante.

Kirill L.
la source
1

05AB1E , 25 octets

΄()1:v"0+0\0->"žuykè.V})

Essayez-le en ligne!

Explication

Î                           # initialize the stack with 0 and the input
 „()1:                      # replace any occurrence of "()" in the input with 1
      v                }    # for each char y in this string
                žuyk        # get its index in the string "()[]<>{}"
       "0+0\0->"    è       # use this to index into the string "0+0\0->"
                     .V     # eval
                        )   # wrap the stack in a list
Emigna
la source
1

R , 182 177 octets

function(P){for(k in utf8ToInt(gsub("\\(\\)",7,P))%%8){if(k%in%0:4)F=c(0,F)
if(k==7)F[1]=F[1]+1
if(k==1)F=c(F[2]+F[3],F[-3:0])
if(k==5)F=c(F[2]-F[1],F[-2:0])
if(k==6)F=F[-1]}
F}

Essayez-le en ligne!

Renvoie la pile, où le haut de la pile est le premier et le bas de la pile est le dernier.

Échange ()avec 7puis calcule les points de code mod 8 pour obtenir des valeurs numériques distinctes, qui sont plus faciles et plus faciles à utiliser que les chaînes.

C'est golfier de travailler avec le début d'un vecteur dans R, donc nous construisons la pile de cette façon.

Ensuite, il voit un ), ou quand k==1, il ajoute un zéro supplémentaire en haut de la pile car il est golfeur de l'ajouter et de le supprimer.

Giuseppe
la source
1

CJam , 29 octets

0q")]>([<""+-;U"er"U+"/')*~]p

Essayez-le en ligne!

0q                              Push 0, input
  ")]>([<""+-;U"er              Translate )]>([< to +-;UUU
                  "U+"/')*      Replace U+ by )
                          ~     Eval as CJam code
                           ]p   Wrap and pretty-print stack
Lynn
la source
1

Ceylan, 285 266 octets

function f(variable String c){variable Integer[]s=[0];value o=>[s[0]else nothing,s=s.rest][0];void u(Integer i)=>s=[i,*s];while(c!=""){if(c[0:2]=="()"){u(1);c=c.rest;}switch(c[0])case(')'){u(o+o);}case(']'){u(-o+o);}case('>'){noop(o);}else{u(0);}c=c.rest;}return s;}

Essayez-le en ligne!

(Enregistré 19 octets en raison d'une suggestion de Leo.)

Formaté et commenté:

// Interpreter for ThirdFlak
// Question:    /codegolf//q/163242/2338
// This answer: /codegolf//a/163403/2338
//
// This function takes the code as a string, and returns the value
// of the stack as a sequence of Integers.
function f(variable String c) {
    // stack, in the beginning just a single 0.
    // Top element of the stack is the first, because push + pop is easier this way.
    variable Integer[] s = [0];
    // pop – used like an Integer variable (not a function – this saves the `()`), but has side effects.
    value o =>
        // `s[0]` is the first element of the stack. We tell the compiler
        // that it is non-null (otherwise we'll get an error at run time)
        // using the `else nothing`. `s.rest` is `s` without its first element.
        // Both together are wrapped into a 2-tuple, of which we then take just
        // the first element, to have both together in an expression instead
        // the longer way using an accessor block with a temporary variable and a return.
        // value o {
        //   value r = s[0] else nothing;
        //   s = s.rest;
        //   return r;
        // }
        [s[0] else nothing, s = s.rest][0];
    // push
    void u(Integer i) =>
        // a tuple enumeration, using the spread argument.
        s = [i, *s];
    // the main loop
    while (c != "") {
        if (c[0:2] == "()") {
            // »`()` is the only two-characters operator in Third-Flak. It increases the top of the third stack by 1.«
            // As `)` alone adds the two top elements together, we can just push a one here, and let the handling for `)` do the rest.
            u(1);
            c = c.rest;
        }
        switch (c[0])
        case (')') {
            // »`)` pops two elements from the third stack and pushes back their sum.«
            u(o + o);
        }
        case (']') {
            // »`]` pops two elements from the third stack and pushes back the result of subtracting the first from the second.«
            // As the o written first is the first one, we can't write this as a subtraction.
            u(-o + o);
        }
        case ('>') {
            // »`>` pops an element from the third stack.«
            // `o;` alone is not a valid statement, so we pass it to the `noop` function.
            noop(o);
        }
        else {
            // all other valid code characters are `(`, `[`, `<`, which all just push a 0.
            u(0);
        }
        c = c.rest;
    }
    return s;
}

Essayez-le en ligne!

Paŭlo Ebermann
la source
Je ne connais pas vraiment Ceylan, mais peut-être pourriez-vous retirer le premier boîtier de l'interrupteur et utiliser l'autre partie pour gérer tous les supports d'ouverture :)
Leo
Hmm, je suppose que cela pourrait fonctionner ... cela changerait le comportement pour une entrée invalide, mais ce n'est pas un problème.
Paŭlo Ebermann