The Third Flak!


19

Questa sfida è stata pubblicata come parte della sfida LotM di aprile 2018


Brain-Flak è un linguaggio turing-tarpit che ha guadagnato molta fama qui su PPCG. La memoria del linguaggio è composta da due pile, ma un terzo "nascosto" è stato scoperto da Wh e at Wizard , portando ad alcuni nuovi modi interessanti di pensare ai programmi Brain-Flak.

Quindi, che ne dite di dare maggiore visibilità a quel povero terzo stack nascosto? Creiamo una lingua in cui il terzo stack ha il riconoscimento che merita! Qui ti presento Third-Flak .

La lingua

In Third-Flak c'è solo uno stack, chiamato terzo stack. Gli operatori dei lavori alla terza pila nello stesso modo che fanno in Brain-Flak, ma qui non ci sono [], {}, <>nilads e non {...}monade (in modo che i caratteri solo ammissibili in un programma di terze Flak sono ()[]<>). Ecco cosa fa ogni operatore (verranno forniti esempi che rappresentano il terzo stack con un elenco in cui l'ultimo elemento è in cima allo stack):

  • ()è l'unico operatore a due caratteri in Third-Flak. Aumenta la parte superiore del terzo stack di 1. Esempio: [1,2,3][1,2,4]

  • (, [, <: Tutte le parentesi di apertura che non sono coperti dal caso precedente spingono una 0alla terza pila. Esempio: [1,2,3][1,2,3,0]

  • )estrae due elementi dal terzo stack e rimanda indietro la loro somma. Esempio: [1,2,3][1,5]

  • ]estrae due elementi dal terzo stack e respinge il risultato della sottrazione del primo dal secondo. Esempio: [1,2,3][1,-1]

  • >apre un elemento dal terzo stack. Esempio [1,2,3][1,2]

Ed ecco le altre regole della lingua:

  • All'inizio dell'esecuzione il terzo stack contiene solo un singolo 0.

  • È vietato avere un programma vuoto []o <>all'interno di un programma (sarebbero comunque noops se seguissero la semantica di Third-Flak, ma in realtà hanno un significato diverso in Brain-Flak che non è possibile ricreare qui).

  • Le parentesi devono sempre essere bilanciate, tranne per il fatto che possono mancare parentesi finali finali alla fine del programma. Ad esempio, [()<(()è un programma Third-Flak valido (e il terzo stack alla fine del programma sarebbe [1,0,1]).

  • Un programma può contenere solo i sei caratteri consentiti ()[]<>. I programmi sono garantiti come non vuoti.

Nota: è implicito dalle regole precedenti che non dovrete affrontare situazioni in cui è necessario pop da uno stack vuoto.

La sfida

Semplice, scrivi un interprete per Third-Flak. Il programma deve prendere come input un programma di terzo flak e restituire come output lo stato del terzo stack alla fine del programma.

Il formato di output è flessibile fintanto che è possibile leggere in modo inequivocabile da esso lo stato del terzo stack e lo stesso numero viene sempre codificato allo stesso modo (Questo è solo un modo per dire che qualsiasi formato di output che non è un modo palese cercare di imbrogliare va bene).

La scelta dell'output può limitare l'intervallo di numeri che è possibile gestire purché ciò non banalizzi la sfida (poiché si tratterebbe di una scappatoia predefinita ).

Casi test

Per ciascun caso di test la prima riga è l'input e la seconda riga lo stack di output rappresentato come un elenco di numeri separato da spazi in cui la parte superiore dello stack è l'ultimo elemento.

[()<(()
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

Lo stack è inizializzato con uno 0? Altrimenti [()]infrange la regola secondo cui non dobbiamo preoccuparci di saltar fuori da una pila vuota
Jo King,

1
@JoKing Yep: "All'inizio dell'esecuzione il terzo stack contiene solo un singolo 0". Forse dovrei evidenziare un po 'quella parte, temevo che sarebbe stato troppo facile perdere.
Leo

Oops, non so come mi sia perso
Jo King,

7
Barrato e è ancora e.
Wheat Wizard

2
Se qualcuno non riesce a vederlo, il barrato eè qui .
user202729

Risposte:


21

Brain-Flak , 276 byte

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

Provalo online!

Dovevi sapere che sarebbe successo.


4

Retina 0.8.2 , 64 48 46 byte

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

Provalo online! Emette lo stack dal basso verso l'alto. Funziona solo con numeri interi non negativi e l'ultimo caso di test è troppo lento, quindi il collegamento include solo tre casi di test. Spiegazione: Lo stack precede implicitamente il programma, quindi inizia come stringa vuota, che rappresenta un singolo zero. Il ()nilad viene trasformato in un _che viene utilizzato per contare in modo unario, mentre le altre parentesi aperte vengono trasformate in nuove righe che spingono uno zero sullo stack quando vengono rilevate. Le parentesi chiuse vengono quindi elaborate una alla volta in modo che lo stack sia corretto; la )cancella il newline precedente, aggiungendo all'inizio due elementi insieme, il ]elimina l'elemento superiore e lo confronta dall'elemento precedente in pila sottraendo così, e>elimina solo l'elemento superiore. Alla fine lo stack viene convertito in decimale. Modifica: salvato 2 byte grazie a @Leo.


A cosa serve $3? (ottima risposta, comunque!)
Leo

@Leo Questo è un residuo di un golf precedente. Grazie per averlo individuato!
Neil,

4

Python 3 , 145 144 132 122 116 109 104 byte

-7 byte grazie a Leo!

E - 5 grazie a Lynn!

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

Provalo online!

Implementazione piuttosto standard. Ora non è così leggibile. Sono deluso di non riuscire a trovare un modo più breve per controllare tra parentesi di inizio e fine.

Alcuni tentativi di one-liner:

  • 124 byte (funzione anonima):

    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 byte (programma completo):

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

Append è fastidiosamente più lungo del semplice incarico


~-']>)'.index(i)può essere (2-ord(i)%5)per salvare 4 byte.
Lynn,

2

Rubino , 98 91 byte

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

Provalo online!

Il mio codice iniziale ha funzionato in modo simile nello spirito alla risposta Python di Jo King, in modo che prima di scorrere i caratteri di origine abbiamo sostituito tutte le ()sottostringhe con un altro personaggio, come operatore distinto.

Tuttavia, almeno in Ruby, è risultato più golfista non farlo, ma piuttosto optare per un approccio leggermente più ingombrante. Qui, manteniamo un indicizzatore aggiuntivo che itiene traccia della nostra posizione nella stringa di origine e ogni volta che si incontra una parentesi aperta, facciamo un lookahead controllando se i nostri caratteri attuali + successivi s[i,2]formano l' ()operatore. In tal caso, spingiamo 1 invece di 0 in cima allo stack e lasciamo che la chiusura )faccia il suo lavoro nel passaggio successivo.


1

05AB1E , 25 byte

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

Provalo online!

Spiegazione

Î                           # 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


1

R , 182 177 byte

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}

Provalo online!

Restituisce la pila, dove la parte superiore della pila è la prima e la parte inferiore della pila è l'ultima.

Scambia ()con 7e quindi calcola i punti di codice mod 8 per ottenere valori numerici distinti, che sono più facili e più golfistici rispetto alle stringhe.

È più golfoso lavorare con l'inizio di un vettore in R, quindi costruiamo lo stack in questo modo.

Quindi vede un ), o quando k==1, aggiunge uno zero in più in cima allo stack poiché è più golfoso aggiungerlo e rimuoverlo.


1

CJam , 29 byte

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

Provalo online!

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

1

Ceylon, 285 266 byte

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;}

Provalo online!

(Salvato 19 byte a causa di un suggerimento di Leo.)

Formattato e commentato:

// 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;
}

Provalo online!


Non conosco davvero Ceylon, ma forse potresti rimuovere il primo caso dell'interruttore e usare l'altra parte per gestire tutte le parentesi aperte :)
Leo

Hmm, immagino che potrebbe funzionare ... cambierebbe il comportamento per input non validi, ma questo non è un problema.
Paŭlo Ebermann,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.