O terceiro tiro!


19

Este desafio foi publicado como parte do desafio do LotM de abril de 2018


Brain-Flak é uma linguagem turp-tarpit que ganhou bastante fama aqui no PPCG. A memória da língua é composto por duas pilhas, mas um "escondido" terceira pilha foi descoberto por Wh e na Wizard , levando a algumas novas formas interessantes de pensar programas Brain-Flak.

Então, que tal dar mais visibilidade à pobre terceira pilha escondida? Vamos criar uma linguagem em que a terceira pilha tenha o reconhecimento que merece! Aqui eu apresento o Terceiro Flak .

O idioma

No Third-Flak, existe apenas uma pilha, chamada terceira pilha. Operadores trabalham no terceiro pilha da mesma forma que fazem em Brain-Flak, mas aqui não há [], {}, <>nilads e nenhuma {...}mônada (assim os personagens única admissível em um terceiro programa-Flak são ()[]<>). Aqui está o que cada operador faz (exemplos serão apresentados representando a terceira pilha com uma lista em que o último elemento é o topo da pilha):

  • ()é o único operador de dois caracteres no Third-Flak. Aumenta o topo da terceira pilha em 1. Exemplo: [1,2,3][1,2,4]

  • (, [, <: Todos os parênteses abertura que não estão abrangidos pelo processo anterior empurrar uma 0para a terceira pilha. Exemplo: [1,2,3][1,2,3,0]

  • )aparece dois elementos da terceira pilha e empurra sua soma. Exemplo: [1,2,3][1,5]

  • ]exibe dois elementos da terceira pilha e empurra para trás o resultado da subtração do primeiro da segunda. Exemplo: [1,2,3][1,-1]

  • >aparece um elemento da terceira pilha. Exemplo [1,2,3][1,2]

E aqui estão as outras regras da linguagem:

  • No início da execução, a terceira pilha contém apenas um único 0.

  • É proibido ter vazio []ou <>dentro de um programa (eles seriam noops de qualquer maneira se seguissem a semântica do Third-Flak, mas na verdade eles têm um significado diferente no Brain-Flak que não é possível recriar aqui).

  • Os parênteses sempre precisam ser equilibrados, exceto pelo fato de que os parênteses finais no final do programa podem estar ausentes. Como exemplo, [()<(()é um programa Third-Flak válido (e a terceira pilha no final do programa seria [1,0,1]).

  • Um programa pode conter apenas os seis caracteres permitidos ()[]<>. Os programas são garantidos como não vazios.

Nota: está implícito nas regras anteriores que você não precisará lidar com situações em que precisa sair de uma pilha vazia.

O desafio

Simples, escreva um intérprete para o Third-Flak. Seu programa deve ter como entrada um programa Third-Flak e retornar como saída o estado da terceira pilha no final do programa.

Seu formato de saída é flexível, desde que seja possível ler de forma inequívoca o estado da terceira pilha e o mesmo número sempre é codificado da mesma maneira (esta é apenas uma maneira de dizer que qualquer formato de saída que não seja flagrante tentar trapacear é bom).

Sua escolha de saída pode restringir o intervalo de números que você pode gerenciar, desde que isso não trivialize o desafio (já que isso seria uma brecha padrão ).

Casos de teste

Para cada caso de teste, a primeira linha é a entrada e a segunda linha, a pilha de saída representada como uma lista de números separados por espaço, onde a parte superior da pilha é o ú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

A pilha é inicializada com um 0? Caso contrário, [()]quebra a regra de que não precisa se preocupar com popping de uma pilha vazia
Jo rei

1
@JoKing Yep: "No início da execução, a terceira pilha contém apenas um único 0". Talvez eu deva destacar um pouco essa parte, eu estava com medo de que fosse fácil demais perder.
Leo

Opa, eu não sei como eu perdi isso
Jo rei

7
Riscado e ainda é e.
Assistente de trigo

2
Se alguém não pode ver isso, o riscado eestá aqui .
usar o seguinte comando

Respostas:


21

Flak cerebral , 276 bytes

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

Experimente online!

Você tinha que saber que isso estava por vir.


4

Retina 0.8.2 , 64 48 46 bytes

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

Experimente online! Produz a pilha de baixo para cima. Funciona apenas com números inteiros não negativos e o último caso de teste é muito lento; portanto, o link inclui apenas três casos de teste. Explicação: A pilha precede implicitamente o programa, portanto, ele inicia como uma sequência vazia, que representa um único zero. O ()nilad é transformado em um _que é usado para contar em unário, enquanto os outros colchetes abertos são transformados em novas linhas que pressionam o zero na pilha à medida que são encontradas. Os colchetes próximos são processados ​​um de cada vez para que a pilha esteja correta; o )exclui a nova linha anterior, adicionando a parte superior dois elementos em conjunto, a ]elimina o elemento superior e as compara a partir do elemento anterior na pilha subtraindo-se assim, e o>apenas exclui o elemento superior. Finalmente, a pilha é convertida em decimal. Editar: salvou 2 bytes graças a @Leo.


Para que serve $3? (grande resposta, de qualquer maneira!)
Leo

@ Leo Isso é uma sobra de um golfe anterior. Obrigado por detectá-lo!
Neil

4

Python 3 , 145 144 132 122 116 116 104 104 bytes

-7 bytes graças a Leo!

E - 5 graças 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)

Experimente online!

Implementação bastante padrão. Agora não é tão legível. Estou decepcionado por não ter conseguido descobrir uma maneira mais curta de verificar entre os parênteses de início e de final.

Algumas tentativas de one-liners:

  • 124 bytes (função 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)

Anexar é irritantemente mais longo que a atribuição simples


~-']>)'.index(i)pode ser (2-ord(i)%5)para salvar 4 bytes.
21418 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}

Experimente online!

Meu código inicial funcionou de maneira semelhante à resposta Python de Jo King, de modo que, antes de percorrer os caracteres de origem, substituímos todas as ()substrings por outro caractere, como um operador distinto.

No entanto, pelo menos em Ruby, descobriu-se que o golfista não fazia isso, mas preferia uma abordagem um pouco mais complicada. Aqui, mantemos um indexador adicional ique monitora nossa posição na string de origem e, sempre que um colchete de abertura é encontrado, fazemos uma inspeção visual verificando se nossos caracteres atuais + próximos s[i,2]formam o ()operador. Nesse caso, pressionamos 1 em vez de 0 no topo da pilha e deixamos o fechamento )fazer seu trabalho na próxima etapa.


1

05AB1E , 25 bytes

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

Experimente online!

Explicação

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

Experimente online!

Retorna a pilha, onde a parte superior da pilha é a primeira e a parte inferior da pilha é a última.

Swaps ()com 7e, em seguida, calcula os pontos de código mod 8 para obter valores numéricos distintos, que são mais fáceis e Golfier do que trabalhar com strings.

É mais golfista trabalhar com o início de um vetor em R, então construímos a pilha dessa maneira.

Em seguida, ele vê um ), ou quando k==1, adiciona um zero extra ao topo da pilha, pois é mais golfista adicioná-lo e removê-lo.


1

CJam , 29 bytes

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

Experimente 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

Ceilão, 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;}

Experimente online!

(Economizou 19 bytes devido a uma sugestão de Leo.)

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

Experimente online!


Eu realmente não sei Ceilão, mas talvez você poderia remover o primeiro caso da chave e usar a parte mais para gerenciar todas as faixas de abertura :)
Leo

Hmm, acho que isso poderia funcionar ... isso mudaria o comportamento de entrada inválida, mas isso não é um problema.
Pa Elo Ebermann 26/04
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.