Pyth é uma linguagem de golfe baseada em Python. Ele usa notação de prefixo, com cada comando tendo uma aridade diferente (número de argumentos que aceita).
Sua tarefa é escrever um verificador de sintaxe para uma linguagem do tipo Pyth (inexistente), Pith.
Sintaxe da medula
O Pith possui apenas 8 comandos de caractere único:
01234()"
01234
cada um tem uma aridade do número correspondente e, portanto, espera muitos argumentos depois dele. Por exemplo,
400010
é um programa Pith correto porque 4
é seguido por quatro argumentos 0
0
0
e 10
, o último dos quais é 1
seguido pelo argumento único 0
. Para visualizar isso, podemos olhar para a seguinte árvore:
R
|
4
|
-------------
| | | |
0 0 0 1
|
0
onde R
é o nó raiz. Uma maneira alternativa de pensar sobre isso é que cada número se refere ao número de filhos que o nó correspondente possui na árvore acima.
Aqui está outro programa Pith válido, com mais de um comando base:
210010
correspondente a
R
|
-------------
| |
2 1
| |
--------- 0
| |
1 0
|
0
Por outro lado,
3120102100
não é um programa Pith correto, porque a inicial 3
possui apenas dois argumentos, que podemos ver observando a árvore abaixo:
R
|
3
|
------------------------ ??
| |
1 2
| |
2 ------
| | |
------ 1 0
| | |
0 1 0
|
0
Em seguida, (
inicia um ilimitado e )
termina um ilimitado. Um ilimitado recebe qualquer número de argumentos (avidamente) e conta como um único argumento para qualquer comando pai. Quaisquer limites ainda abertos até o final do programa são fechados automaticamente. Um )
comando não é um erro se não houver limites ilimitados - ele simplesmente não faz nada. *
Por exemplo, o programa Pith
)31(0)0(201000100
corresponde à árvore
R
|
3
|
------------------------------
| | |
1 0 (
| |
( -----------------------------
| | | | | |
0 2 0 0 1 0
| |
------- 0
| |
0 1
|
0
Os limites ilimitados são ()
válidos , assim como um programa Pith válido.
Um programa Pith inválido com um limite é
12(010
já que o 2
único recebe um argumento (o ilimitado).
Finalmente, "
inicia e termina uma string, que é sempre 0 arity e conta como um único argumento, por exemplo
2"010""44)()4"
que é apenas uma 2
passagem de dois argumentos de string "010"
e "44)()4"
. Como sem limites, as seqüências de caracteres também podem estar vazias, e quaisquer seqüências de caracteres não fechadas no final do programa são fechadas automaticamente.
* Esta parte é diferente do Pyth original, que realmente faz algo em um caso como 1)
, encerrando a aridade 1 e gerando um erro.
Entrada / saída
A entrada será uma única seqüência de caracteres não vazia que consiste apenas nos caracteres 01234()"
. Opcionalmente, você pode assumir que uma nova linha à direita adicional esteja sempre presente. Você pode escrever uma função ou um programa completo para esse desafio.
Você deve gerar um valor verdadeiro se a entrada for Pith sintaticamente válida ou um valor falso, caso contrário. Os valores de verdade e falsidade devem ser fixos, para que você não possa produzir 1
para um programa válido e 2
para outro.
Pontuação
Isso é código-golfe, então o código com o menor número de bytes vence.
Casos de teste
Verdade:
0
)
(
"
()
""
10
400010
210010
("")00
3"""""
(0)))0)1)0
2(2(2(0)0)0)0
2"010""44)()4"
)31(0)0(201000100
())2)1))0"3())"))
3("4321("301(0)21100"4")"123"00)40"121"31000""01010
Falsy:
1
1(310
(1)0)
12(010
4"00010"
3120102100
20(2((0)(0)))
2(2(2(0)0)0)01)
4(0102)00)00000
2"00"("00"2(""))
fonte
[( [2 [0] [1 [0] ] ] [0] [1 [0]] [0] ]
? O que você tem possui ramificações de 2, 0, 0, 1 e 0 - o segundo não deve estar lá.())2)1))0"3())"))
(o que deve ser verdade, eu acho).()210""
com um monte de não-ops)Respostas:
CJam, 65 bytes
Puxa, eu gostaria que o CJam tivesse Regex, isso poderia ter sido concluído em menos de 50 bytes
A idéia principal é continuar reduzindo as coisas para
0
ie10
para0
,200
para0
e assim por diante. Uma vez feito isso, podemos reduzir todas as faixas corresponde a0
, ou seja,()
para0
,(0)
para0
,(00)
para0
e assim por diante. Repetimos osL
tempos do ciclo , ondeL
está o comprimento da entrada.A string de entrada inicialmente passa por um processamento extra, onde ajustamos para incomparável
"
e adicionamos muito)
para compensar por incomparável(
Isso garante que, após todas as iterações, devamos ter
0
(e não-op)
) apenas a string.Atualização - foi corrigido um erro em que as operações
)
não operacionais de nível superior são consideradas prejudiciaisExpansão de código
Experimente online aqui ou execute todo o conjunto
fonte
Regex, sabor PCRE, 83 bytes
Experimente aqui.
Regex, sabor PCRE, 85 bytes
Experimente aqui.
Usamos algumas idéias na resposta deste dan1111 .
Algumas explicações sobre
(?2)*(()(?1))?
.fonte
(?2)*(()(?1))?
é a peça final do quebra-cabeça que eu estava procurando. Boa descoberta! ;)(?2)*(()(?1))?
parte corretamente, a(()(?1))?
peça nunca corresponde a nada, pois(?2)*
já consome tudo o que(()(?1))?
pode corresponder, e essa construção é usada para definir o grupo de captura 3 quando entramos(
e desmarcar o grupo de captura 3 quando estamos fora da()
construção (para permitir a correspondência não emparelhado)
).lex, 182 bytes (157 com pilha de tamanho fixo)
Esses programas requerem que a entrada seja uma única sequência terminada de nova linha de caracteres válidos.
O programa acima falhará se ficar sem memória, o que teoricamente poderia acontecer se você o suficiente
(
. Mas como um segfault conta como falha, eu estou tomando isso como "falsey", embora a descrição do problema não diga o que fazer se os recursos não forem suficientes.Cortei 157 bytes usando apenas uma pilha de tamanho fixo, mas isso parecia trapaça.
Compilar:
Teste:
Saída de teste:
fonte
80386 Montador, 97 bytes
Despejo hexagonal:
Isso percorre a entrada uma vez, pressionando números maiores que zero na pilha e diminuindo-os quando um zero é processado. Não consolidadas são processadas como -1.
Protótipo da função (em C) (a função retorna 0 se inválida e 1 se válida):
Montagem equivalente (NASM):
O código a seguir em C pode ser usado com o GCC em um sistema POSIX para testar:
fonte
Python 2, 353 bytes
A função de análise percorre os tokens um de cada vez e cria uma árvore da estrutura do programa. Programas inválidos acionam uma exceção que causa a impressão de um zero (Falsy); caso contrário, a análise bem-sucedida resulta em um.
A saída dos testes mostrando a saída do analisador:
O código antes do minificador:
fonte
==
pelos testes - colocando as strings primeiro significa que você pode fazerif')'==q
. Acredito que uma dasbreak
declarações poderia ser substituída porf=0
, pois isso também owhile f
tirará do circuito. Finalmente, em vez deassert x==y
você pode usar1/(x==y)
para aZeroDivisionError
. ;)Pip ,
8872 bytesIdeia retirada do CJam do Optimizer . Minha facada original no problema de um analisador de descida recursivo foi ... bastante mais longa.
Formatado, com explicação:
Truques interessantes:
0X,5
, por exemplo, é0 X [0 1 2 3 4] == ["" "0" "00" "000" "0000"]
.R
operador moran Jr. pode ter uma lista para qualquer um dos seus argumentos:"abracadabra" R ["br" "ca"] 'b
dáababdaba
, por exemplo. Faço bom uso desse recursoz
aqui.""
vazia[]
, a lista vazia e qualquer escalar que seja zero. Assim,0
é falso, mas também0.0
e"0000000"
. Às vezes, esse recurso é inconveniente (para testar se uma string está vazia, é preciso testar seu comprimento porque também"0"
é falso), mas, para esse problema, é perfeito.fonte
Javascript (ES6),
289288285282278244241230 bytesfonte