El tercer flak!

19

Este desafío se publicó como parte del desafío LotM de abril de 2018


Brain-Flak es un lenguaje turing-tarpit que ha ganado mucha fama aquí en PPCG. La memoria de la lengua está compuesta por dos pilas, sino una "oculta" tercera pila fue descubierto por Wh correo al asistente , lo que lleva a algunas nuevas formas de pensar interesantes programas Cerebro-Flak.

Entonces, ¿qué pasa con dar a esa pobre tercera pila oculta más visibilidad? ¡Creemos un lenguaje donde la tercera pila tenga el reconocimiento que merece! Aquí te presento Third-Flak .

El idioma

En Third-Flak solo hay una pila, llamada la tercera pila. Los operadores trabajan en la tercera pila de la misma manera que lo hacen en Brain-Flak, pero aquí no hay [], {}, <>nilads y sin {...}mónada (por lo que los personajes sólo es admisible en un programa de otro son Flak ()[]<>). Esto es lo que hace cada operador (se darán ejemplos que representan la tercera pila con una lista donde el último elemento es la parte superior de la pila):

  • ()es el único operador de dos caracteres en Third-Flak. Aumenta la parte superior de la tercera pila en 1. Ejemplo: [1,2,3][1,2,4]

  • (, [, <: Todos los paréntesis de apertura que no están cubiertos por el caso anterior empujan una 0a la tercera pila. Ejemplo: [1,2,3][1,2,3,0]

  • )saca dos elementos de la tercera pila y hace retroceder su suma. Ejemplo: [1,2,3][1,5]

  • ]saca dos elementos de la tercera pila y hace retroceder el resultado de restar el primero del segundo. Ejemplo: [1,2,3][1,-1]

  • >saca un elemento de la tercera pila. Ejemplo [1,2,3][1,2]

Y aquí están las otras reglas del lenguaje:

  • Al comienzo de la ejecución, la tercera pila contiene solo un 0.

  • Está prohibido tener un programa vacío []o <>dentro (de todos modos, serían noops si siguieran la semántica de Third-Flak, pero en realidad tienen un significado diferente en Brain-Flak que no es posible recrear aquí).

  • Los paréntesis siempre deben estar equilibrados, excepto por el hecho de que pueden faltar los paréntesis finales al final del programa. Como ejemplo, [()<(()es un programa válido de Third-Flak (y la tercera pila al final del programa sería [1,0,1]).

  • Un programa solo puede contener los seis caracteres permitidos ()[]<>. Se garantiza que los programas no están vacíos.

Nota: está implícito en las reglas anteriores que no tendrá que lidiar con situaciones en las que necesita estallar desde una pila vacía.

El reto

Simple, escriba un intérprete para Third-Flak. Su programa debe tomar como entrada un programa Third-Flak y devolver como salida el estado de la tercera pila al final del programa.

Su formato de salida es flexible siempre que sea posible leer de manera inequívoca el estado de la tercera pila y el mismo número siempre se codifica de la misma manera (Esta es solo una forma de decir que cualquier formato de salida que no sea una forma evidente intentar hacer trampa está bien).

Su elección de salida puede restringir el rango de números que puede administrar siempre que esto no trivialice el desafío (ya que esto sería una laguna predeterminada ).

Casos de prueba

Para cada caso de prueba, la primera línea es la entrada, y la segunda línea la pila de salida representada como una lista de números separados por espacios donde la parte superior de la pila es el último 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
León
fuente
¿La pila se inicializa con un 0? De lo contrario, se [()]rompe la regla de que no debemos preocuparnos por estallar desde una pila vacía
Jo King,
1
@JoKing Yep: "Al comienzo de la ejecución, la tercera pila contiene solo un 0". Tal vez debería resaltar un poco esa parte, temía que hubiera sido demasiado fácil pasarlo por alto.
Leo
Vaya, no sé cómo me perdí eso
Jo King
77
Tachado e sigue siendo e.
Wheat Wizard
2
Si alguien no puede ver eso, el tachado eestá aquí .
user202729

Respuestas:

21

Brain-Flak , 276 bytes

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

Pruébalo en línea!

Tenías que saber que esto iba a suceder.

Nitrodon
fuente
4

Retina 0.8.2 , 64 48 46 bytes

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

Pruébalo en línea! Emite la pila de abajo hacia arriba. Solo funciona con enteros no negativos, y el último caso de prueba es demasiado lento, por lo que el enlace solo incluye tres casos de prueba. Explicación: La pila precede implícitamente al programa, por lo que comienza como una cadena vacía, que representa un solo cero. El ()nilad se convierte en uno _que se usa para contar en unario, mientras que los otros corchetes abiertos se convierten en nuevas líneas que empujan un cero a la pila a medida que se encuentran. Los corchetes se procesan uno a la vez para que la pila sea correcta; El )borra la nueva línea anterior, sumando los dos elementos superiores, ]borra el elemento superior y lo combina con el elemento anterior en la pila, restándolo, y el>solo elimina el elemento superior. Finalmente la pila se convierte a decimal. Editar: Guardado 2 bytes gracias a @Leo.

Neil
fuente
¿Qué es la $3de? (¡gran respuesta, de todos modos!)
Leo
@Leo Eso es un sobrante de un golf anterior. ¡Gracias por verlo!
Neil
4

Python 3 , 145144132122116109104 bytes

-7 bytes gracias a Leo!

Y - 5 gracias 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)

Pruébalo en línea!

Implementación bastante estándar. Sin embargo, ahora no es tan legible. Sin embargo, estoy decepcionado porque no pude encontrar una forma más corta de verificar entre los corchetes de inicio y fin.

Algunos intentos de una línea:

  • 124 bytes (función anónima):

    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 bytes (programa completo):

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

Append es molestamente más largo que la asignación simple

Jo King
fuente
~-']>)'.index(i)puede ser (2-ord(i)%5)para guardar 4 bytes.
Lynn
2

Ruby , 98 91 bytes

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

Pruébalo en línea!

Mi código inicial funcionó de manera similar en espíritu a la respuesta de Python de Jo King, por lo que antes de recorrer los caracteres de origen reemplazamos todas las ()subcadenas por otro carácter, como un operador distinto.

Sin embargo, al menos en Ruby, resultó más golfista no hacer esto, sino más bien adoptar un enfoque un poco más engorroso. Aquí, mantenemos un indexador adicional que realiza un iseguimiento de nuestra posición en la cadena de origen, y cada vez que se encuentra un paréntesis de apertura, hacemos una búsqueda anticipada para verificar si nuestros caracteres actuales + siguientes s[i,2]forman el ()operador. En ese caso, presionamos 1 en lugar de 0 en la parte superior de la pila y dejamos que el cierre )haga su trabajo en el siguiente paso.

Kirill L.
fuente
1

05AB1E , 25 bytes

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

Pruébalo en línea!

Explicación

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

R , 182 177 bytes

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}

Pruébalo en línea!

Devuelve la pila, donde la parte superior de la pila es la primera y la parte inferior de la pila es la última.

Swaps ()con 7y luego calcula los puntos de código mod 8 para obtener los valores numéricos distintos, que son más fáciles y Golfier de trabajar que las cuerdas.

Es más golfista trabajar con el comienzo de un vector en R, por lo que construimos la pila de esa manera.

Luego ve un ), o cuando k==1, agrega un cero extra a la parte superior de la pila ya que es más golfoso agregarlo y eliminarlo.

Giuseppe
fuente
1

CJam , 29 bytes

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

Pruébalo en línea!

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

Ceilán, 285 266 bytes

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

Pruébalo en línea!

(Se guardaron 19 bytes debido a una sugerencia de Leo).

Formateado y comentado:

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

Pruébalo en línea!

Paŭlo Ebermann
fuente
Realmente no conozco a Ceilán, pero tal vez podrías quitar la primera caja del interruptor y usar la otra parte para administrar todos los corchetes de apertura :)
Leo
Hmm, supongo que eso podría funcionar ... cambiaría el comportamiento de la entrada no válida, pero eso no es un problema.
Paŭlo Ebermann