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!;
BlockScript es un lenguaje trivial basado en la pila de espagueti que creé específicamente para este desafío. El intérprete base es blockscript.c .
Programa de muestra (imprime los primeros 15 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!
;
El intérprete lee el código fuente y la entrada del programa desde la entrada estándar, en ese orden. Esto significa que para ejecutar un intérprete dentro de un intérprete dentro de un intérprete, simplemente copie y pegue:
# 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!
;
Al igual que la película Inception , prácticamente no puedes ir más allá de los tres niveles. No es cuestión de tiempo, sino de espacio. BlockScript pierde profusamente la memoria, y esto tiene que ver con cómo está diseñado el lenguaje en sí.
Referencia idiomática:
Consigue el intérprete aquí
En BlockScript, la "pila" no es una matriz que se sobrescribe por operaciones posteriores como está acostumbrado. En realidad, se implementa como una lista vinculada inmutable, y una pila persiste durante la duración del programa. Además, ningún operador (excepto @
) elimina valores de la pila. Sin embargo, las modificaciones de la pila solo afectan el bloque en el que ocurren.
Selección de valor
a
mediante z
Obtenga el elemento 0-25o de la pila y empújelo hacia la pila. a
se refiere a la cabeza, o al elemento empujado más recientemente, de la pila.
A
mediante Z
Obtenga el elemento 0-25 del marco actual y empújelo a la pila.
[
Abra un "marco" para seleccionar elementos de la referencia de la pila (ver más abajo) en el encabezado de la pila. [
no requiere una coincidencia ]
, pero los marcos tienen un alcance léxico. En BlockScript, el "alcance" está determinado por llaves ( {
... }
) que forman bloques. Por lo tanto, abrir un marco dentro de un bloque no tendrá ningún efecto en el código fuera del bloque.
]
Cierre el marco actual, volviendo al marco anterior (si lo hay).
Bloques
{
... }
Crea un "bloque" y empújalo a la pila. Dentro de un bloque, la pila comenzará en lo que era antes del bloque, excepto que la pila de la persona que llama será empujada hacia arriba. Las pilas son persistentes e inmutables en BlockScript, por lo que los bloques son cierres. El modismo {[
significa abrir un bloque, luego abrir un marco para comenzar a seleccionar argumentos (usando a A
través de Z
). El valor de retorno de un bloque es la cabeza de la pila cuando }
se alcanza.
Ejemplo:
'3 '2 '1 {[ b. d. f. B. C. D. A! } 'D 'C 'B d!;
Esto imprime 123BCD123DCB123BCD123DCB…
. Las letras minúsculas se refieren a los valores de la pila, mientras que las letras mayúsculas se refieren a los argumentos (porque el marco se establece en la pila de la persona que llama). A!
toma la cabeza de la persona que llama (que se garantiza que es el bloque que se llama) y lo llama. Si se pregunta por qué se invierte BCD
cada dos veces, es porque B. C. D.
empuja esos argumentos en orden inverso justo antes de que el bloque se llame a sí mismo.
!
Llamar a un bloque. Empuje el valor de retorno a la pila.
Referencias de pila
&
Cree una referencia de pila y empújela a la pila. Piense en esto como "super-contras", ya que efectivamente toma cada elemento en la pila y forma una "tupla". La expresión &[
significa que cualquier cosa a
, b
, c
hace referencia ahora se puede acceder antes con A
, B
, C
(para el resto del bloque o hasta que ]
se encuentra).
En parte porque &
captura más valores de los que generalmente necesita, BlockScript pierde memoria por diseño.
@
Cambie a la pila a la que apunta la referencia de la pila a
. Este operador es bastante extraño, pero el autointerpretador BlockScript lo usa un par de veces para evitar tener que empujar los mismos argumentos dos veces. Los efectos de @
(o cualquier operación de pila, para el caso) se limitan al bloque en el que se invoca. Además, el marco no se ve afectado @
, por lo que se puede usar para tomar los valores que necesita después de cambiar las pilas.
Expresión condicional
?
<en verdadero> :
<en falso>
Expresión condicional, al igual que el operador ternario en C. Es decir, si a
es "verdadero" (es decir, no es igual al entero cero), entonces haga <en verdadero> , de lo contrario haga <en falso> .
I / O
Nota: La entrada y salida se realizan en UTF-8. Un "carácter" es un número entero que corresponde a un índice Unicode.
,
Obtenga el siguiente carácter de entrada y empújelo a la pila. Si se alcanza el final de la entrada, presione -1 en su lugar.
.
Salida del personaje en la cabeza de la pila.
Enteros / literales de caracteres
Nota: Los enteros y los caracteres son lo mismo en BlockScript.
Aritmética
Estos operadores solo funcionan con valores enteros.
+
Compute b
+ a
(empujando el resultado, pero sin descartar ninguno de los valores).
-
Calcular b
- a
.
*
Calcular b
* a
.
/
Calcular b
/ a
(división entera; se redondea hacia el infinito negativo).
%
Calcular b
% a
(módulo entero; se redondea hacia el infinito negativo).
Operadores relacionales
Estos operadores solo funcionan con valores enteros.
<
Si b
es menor que a
, presione 1, de lo contrario presione 0.
>
=
Diverso
#
Comentario al final de la línea
- El programa debe terminar con
;
- Todos los demás personajes son ignorados.
/usr/bin/cat
) ¿qué pasa con la integridad de Turing?