BlockScript - 535
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;
O BlockScript é uma linguagem trivial baseada em pilha de espaguetes que criei especificamente para esse desafio. O intérprete de base é blockscript.c .
Programa de amostra (imprime os 15 primeiros números de Fibonacci):
{[B?B10/A!B10%d&:0}
{[B0<?'-.0B-A!:{B?Bh!{[B?B[A]A!B[B]'0+.:}!:'0.}!10.}
{[B?Dd!DC+B1-CecA!:}
0 1 15d!
;
O intérprete lê o código fonte e a entrada do programa a partir da entrada padrão, nessa ordem. Isso significa que, para executar um intérprete dentro de um intérprete, copie e cole:
# Level 1
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;
# Level 2
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;
# Level 3
{[B?B10/A!B10%d&:0}
{[B0<?'-.0B-A!:{B?Bh!{[B?B[A]A!B[B]'0+.:}!:'0.}!10.}
{[B?Dd!DC+B1-CecA!:}
0 1 15d!
;
Como o filme Inception , você praticamente não pode ir além de três níveis. Não é uma questão de tempo, mas de espaço. O BlockScript vaza memória profusamente, e isso tem a ver com a forma como a própria linguagem é projetada.
Referência de idioma:
Obtenha o intérprete aqui
No BlockScript, a "pilha" não é uma matriz que é substituída por operações subseqüentes como você pode estar acostumado. Na verdade, é implementado como uma lista vinculada imutável e uma pilha persiste durante o programa. Além disso, nenhum operador (exceto @
) remove valores da pilha. No entanto, as modificações da pilha afetam apenas o bloco em que ocorrem.
Seleção de valor
a
através z
Busque o item 0-25º da pilha e empurre-o para a pilha. a
refere-se ao cabeçalho, ou item empurrado mais recentemente, da pilha.
A
através Z
Busque o item 0-25º do quadro atual e empurre-o para a pilha.
[
Abra um "quadro" para selecionar itens da referência da pilha (veja abaixo) no cabeçalho da pilha. [
não exige uma correspondência ]
, mas os quadros têm escopo lexicamente. No BlockScript, "escopo" é determinado por chaves ( {
... }
) que formam blocos. Assim, abrir um quadro dentro de um bloco não terá efeito no código fora do bloco.
]
Feche o quadro atual, retornando ao quadro anterior (se houver).
Blocos
{
... }
Crie um "bloco" e empurre-o para a pilha. Dentro de um bloco, a pilha começará do que era antes do bloco, exceto que a pilha do chamador será empurrada para cima. As pilhas são persistentes e imutáveis no BlockScript, portanto, os blocos são encerramentos. O idioma {[
significa abrir um bloco e, em seguida, abrir um quadro para começar a selecionar argumentos (usando A
através Z
). O valor de retorno de um bloco é o cabeçalho da pilha quando }
é atingido.
Exemplo:
'3 '2 '1 {[ b. d. f. B. C. D. A! } 'D 'C 'B d!;
Isso imprime 123BCD123DCB123BCD123DCB…
. As letras minúsculas se referem aos valores da pilha, enquanto as letras maiúsculas se referem aos argumentos (porque o quadro está definido como a pilha do chamador). A!
pega o chefe do chamador (que é garantidamente o bloco que está sendo chamado) e o chama. Se você está se perguntando por que ele reverte BCD
todas as vezes, é porque B. C. D.
envia esses argumentos na ordem inversa antes do bloco se chamar.
!
Ligue para um bloco. Empurre o valor de retorno para a pilha.
Referências de pilha
&
Crie uma referência de pilha e empurre-a para a pilha. Pense nisso como "superconvenientes", pois efetivamente pega todos os itens da pilha e forma uma "tupla". O idioma &[
significa que tudo a
, b
, c
referidas antes de agora pode ser acessado com A
, B
, C
(para o restante do bloco ou até que ]
seja encontrado).
Em parte porque &
captura mais valores do que normalmente precisa, o BlockScript vaza memória por design.
@
Alterne para a pilha apontada pela referência da pilha a
. Esse operador é um pouco estranho, mas o auto-intérprete BlockScript o usa algumas vezes para evitar ter que empurrar os mesmos argumentos duas vezes. Os efeitos de @
(ou qualquer operação de pilha, nesse caso) são limitados ao bloco em que é invocado. Além disso, o quadro não é afetado @
, portanto, o quadro pode ser usado para obter os valores necessários após a troca de pilhas.
Expressão condicional
?
<em verdadeiro> :
<em falso>
Expressão condicional, assim como o operador ternário em C. Ou seja, se a
for "true" (ou seja, não for igual ao número inteiro zero), faça <em true> , caso contrário <em false> .
I / O
Nota: A entrada e a saída são feitas em UTF-8. Um "caractere" é um número inteiro correspondente a um índice Unicode.
,
Obtenha o próximo caractere de entrada e empurre-o para a pilha. Se o final da entrada for alcançado, pressione -1 em vez disso.
.
Coloque o caractere na cabeça da pilha.
Literais de número inteiro / caractere
Nota: Inteiros e caracteres são a mesma coisa no BlockScript.
Aritmética
Esses operadores trabalham apenas em valores inteiros.
+
Calcule b
+ a
(pressionando o resultado, mas não descartando nenhum valor).
-
Computar b
- a
.
*
Computar b
* a
.
/
Computar b
/ a
(divisão inteira; arredonda para o infinito negativo).
%
Calcule b
% a
(módulo inteiro; arredonda para o infinito negativo).
Operadores relacionais
Esses operadores trabalham apenas em valores inteiros.
<
Se b
for menor que a
, pressione 1, depois pressione 0.
>
=
Diversos
#
Comentar até o final da linha
- O programa deve terminar com
;
- Todos os outros caracteres são ignorados.
/usr/bin/cat
) e quanto à integridade de Turing?