O cálculo SKI é uma variante do cálculo Lambda que não usa expressões lambda. Em vez disso, apenas o aplicativo e os combinadores S , K e I são usados. Nesse desafio, sua tarefa é converter os termos de SKI em termos do Lambda na forma normal β .
Especificação de entrada
A entrada é um termo SKI na seguinte representação textual. Você pode optar por receber uma nova linha opcional à direita. A entrada é composto por caracteres S
, K
, I
, (
, e )
e satisfaz a seguinte gramática (em forma ABNF) com sterm
sendo o símbolo inicial:
sterm = sterm combinator ; application
sterm = combinator ;
sterm = '(' sterm ')' ; grouping
combinator = 'S' | 'K' | 'I' ; primitives
Especificação de saída
A saída é um termo lambda sem variáveis livres na seguinte representação textual. Você pode optar por gerar uma nova linha à direita opcional. A saída deve satisfazer a seguinte gramática no formato ABNF, lterm
sendo o símbolo inicial:
lterm = lterm operand ; application
lterm = ALPHA '.' lterm ; lambda
lterm = operand
operand = '(' lterm ')' ; grouping
operand = ALPHA ; variable (a letter)
Restrições
Você pode assumir que a entrada possui uma forma normal β. Você pode supor que a forma normal β use no máximo 26 variáveis diferentes. Você pode assumir que entrada e saída são representáveis em 79 caracteres.
Entradas de Amostra
Aqui estão algumas entradas de amostra. A saída é uma saída possível para a entrada especificada.
input output
I a.a
SKK a.a
KSK a.b.c.ac(bc)
SII a.aa
Pontuação
A solução mais curta em octetos vence. Falhas comuns são proibidas.
sterm
elterm
usar a associação à esquerda quando houver colchetes ausentes.SKI
comoS(KI)
.Respostas:
Haskell , 232 bytes
Experimente online!
Como funciona
Este é um front-end de analisador diferente da minha resposta para "Escreva um intérprete para o cálculo lambda não digitado " , que também possui uma versão não destruída com documentação.
Resumidamente,
Term = T (Char -> String)
é o tipo de termos de cálculo lambda, que sabe como se aplicar a outros termos (a :: Term -> Term -> Term
) e como se exibir como aString
((%) :: Term -> Char -> String
), dada uma variável nova inicial como aChar
. Podemos converter uma função em termos para um termo coml :: (Term -> Term) -> Term
e, como a aplicação do termo resultante simplesmente chama a função (a (l f) == f
), os termos são automaticamente reduzidos à forma normal quando exibidos.fonte
Ruby, 323 bytes
Não acredito que esse pedaço de porcaria funcione:
Usar a substituição de regex para executar a redução de β em strings brutas é algo do Tony-the-Pony. No entanto, sua saída parece correta, pelo menos, para casos de teste fáceis:
Aqui está como lidar
K(K(K(KK)))
com alguma saída de depuração, que leva cerca de 7 segundos no meu laptop, porque a recursão da expressão regular é lenta . Você pode ver sua conversão α em ação!fonte
Python 2, 674
Nota: depois
while 1:
, três linhas são recuadas com um caractere de tabulação.Este é basicamente o código por trás do http://ski.aditsu.net/ , traduzido para python, bastante simplificado e com muita ação.
Referência: (isso provavelmente é menos útil agora que o código está compactado)
V = termo variável
A = termo de aplicação
L = termo lambda
c = contador de variável
p = substituir variável pelo termo
r = reduzir
m = renumeração final da variável
u = renumeração interna da variável (para termos duplicados)
s = conversão de string
(parâmetro s = self)
C = caractere (s) separador (s) para conversão de string
I, K, S: combinadores
E = analisar
Exemplos:
(isto ↑ é esperado porque
SII(SII)
é irredutível)Obrigado Mauris e Sp3000 por ajudar a matar um monte de bytes :)
fonte
def m(a,b,c):return foo
emm=lambda a,b,c:foo
classes internas, o que pode economizar muitos bytes.a.b.c.a(c)(b(c))
como uma expressão lambda válida: o que é(c)
?Lisp comum, 560 bytes
"Finalmente, encontrei um uso para
PROGV
".Ungolfed
Redução beta
As variáveis são ligadas dinamicamente durante a redução com os
PROGV
novos símbolos Common Lisp, usandoMAKE-SYMBOL
. Isso permite evitar bem as colisões de nomes (por exemplo, sombreamento indesejável de variáveis associadas). Eu poderia ter usadoGENSYM
, mas queremos ter nomes fáceis de usar para símbolos. É por isso que os símbolos são nomeados com letras de aaté z(conforme permitido pela pergunta).N
representa o código de caractere da próxima letra disponível no escopo atual e começa com 97, também conhecido como a.Aqui está uma versão mais legível de
R
(sem aW
macro):Resultados intermediários
Analisar a partir da string:
Reduzir:
(Veja traço de execução)
Pretty-print:
Testes
Eu reutilizo o mesmo conjunto de testes que a resposta do Python:
O oitavo exemplo de teste é muito grande para a tabela acima:
a.a.a.a.a.b.a
está correcta e não usam tanto letras como a resposta do Python, onde as ligações aa
,b
,c
ed
não são referenciados.atuação
O loop nos 7 testes aprovados acima e a coleta dos resultados são imediatos (saída da SBCL):
Fazer o mesmo teste centenas de vezes leva a ... "Armazenamento local de threads esgotado" na SBCL, devido a uma limitação conhecida em relação a variáveis especiais. Com o CCL, chamar a mesma suíte de testes 10000 vezes leva 3,33 segundos.
fonte