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 è un linguaggio banale basato su stack di spaghetti che ho creato appositamente per questa sfida. L'interprete di base è blockscript.c .
Programma di esempio (stampa i primi 15 numeri di 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!
;
L'interprete legge sia il codice sorgente che l'input del programma dall'input standard, in quell'ordine. Ciò significa che per eseguire un interprete all'interno di un interprete all'interno di un interprete, è sufficiente copiare e incollare:
# 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!
;
Come nel film Inception , praticamente non puoi andare più in profondità di tre livelli. Non è una questione di tempo, ma di spazio. BlockScript perde abbondantemente la memoria, e questo ha a che fare con il modo in cui è progettato il linguaggio stesso.
Lingua di riferimento:
Prendi l'interprete qui
In BlockScript, lo "stack" non è un array che viene sovrascritto da operazioni successive come è possibile fare. In realtà è implementato come un elenco collegato immutabile e uno stack persiste per la durata del programma. Inoltre, nessun operatore (tranne @
) rimuove i valori dallo stack. Tuttavia, le modifiche allo stack influiscono solo sul blocco in cui si verificano.
Selezione del valore
a
attraverso z
Prendi lo 0-25 ° oggetto dallo stack e spingilo nello stack. a
si riferisce alla testa, o all'ultimo oggetto spinto, della pila.
A
attraverso Z
Prendi l'elemento 0-25 del fotogramma corrente e spingilo nello stack.
[
Apri una "cornice" per selezionare gli elementi dal riferimento della pila (vedi sotto) sulla testa della pila. [
non richiede una corrispondenza ]
, ma i frame hanno un ambito lessicale. In BlockScript, "scope" è determinato da parentesi graffe ( {
... }
) che formano blocchi. Pertanto, l'apertura di un frame all'interno di un blocco non avrà alcun effetto sul codice esterno al blocco.
]
Chiude il fotogramma corrente, tornando al fotogramma precedente (se presente).
blocchi
{
... }
Crea un "blocco" e spingilo nello stack. All'interno di un blocco, lo stack inizierà da quello che era prima del blocco, tranne che lo stack del chiamante verrà spinto in alto. Le pile sono persistenti e immutabili in BlockScript, quindi i blocchi sono chiusure. Il linguaggio {[
significa aprire un blocco, quindi aprire un frame per iniziare a selezionare gli argomenti (usando A
through Z
). Il valore di ritorno di un blocco è il capo dello stack quando }
viene raggiunto.
Esempio:
'3 '2 '1 {[ b. d. f. B. C. D. A! } 'D 'C 'B d!;
Questo stampa 123BCD123DCB123BCD123DCB…
. Le lettere minuscole si riferiscono ai valori dello stack, mentre le lettere maiuscole si riferiscono agli argomenti (poiché il frame è impostato sullo stack del chiamante). A!
prende il capo del chiamante (che è garantito essere il blocco chiamato) e lo chiama. Se ti stai chiedendo perché si inverte BCD
ogni altra volta, è perché inserisce B. C. D.
quegli argomenti in ordine inverso proprio prima che il blocco si richiami.
!
Chiama un blocco. Spingere il valore restituito nello stack.
Riferimenti dello stack
&
Creare un riferimento di stack e trasferirlo nello stack. Pensa a questo come "super-contro", in quanto prende effettivamente ogni oggetto in pila e ne forma una "tupla". Il linguaggio &[
mezzi che qualunque a
, b
, c
di cui prima ora possono essere raggiunti con A
, B
, C
(per il resto del blocco o finché ]
si incontra).
In parte perché &
acquisisce più valori di quanti ne richiedano normalmente, BlockScript perde memoria in base alla progettazione.
@
Passa allo stack indicato dal riferimento dello stack a
. Questo operatore è piuttosto strano, ma l'auto-interprete BlockScript lo usa un paio di volte per evitare di dover spingere due volte gli stessi argomenti. Gli effetti di @
(o qualsiasi operazione di stack, per quella materia) sono limitati al blocco in cui viene invocato. Inoltre, il frame non è interessato da @
, quindi il frame può essere usato per afferrare i valori necessari dopo il cambio di stack.
Espressione condizionale
?
<su vero> :
<su falso>
Espressione condizionale, proprio come l'operatore ternario in C. Cioè, se a
è "vero" (cioè non è uguale allo zero intero), allora fai <su vero> , altrimenti fai <su falso> .
I / O
Nota: l'ingresso e l'output vengono eseguiti in UTF-8. Un "carattere" è un numero intero corrispondente a un indice Unicode.
,
Ottieni il prossimo carattere di input e spingilo nello stack. Se viene raggiunta la fine dell'input, premere invece -1.
.
Emetti il personaggio in testa alla pila.
Letterali interi / caratteri
Nota: numeri interi e caratteri sono la stessa cosa in BlockScript.
Aritmetica
Questi operatori funzionano solo su valori interi.
+
Calcola b
+ a
(spingendo il risultato, ma non scartando nessuno dei due valori).
-
Calcola b
- a
.
*
Calcola b
* a
.
/
Calcola b
/ a
(divisione intera; arrotonda all'infinito negativo).
%
Calcola b
% a
(modulo intero; arrotonda all'infinito negativo).
Operatori relazionali
Questi operatori funzionano solo su valori interi.
<
Se b
è inferiore a
, premere 1, altrimenti premere 0.
>
=
miscellaneo
#
Commenta alla fine della riga
- Il programma deve terminare con
;
- Tutti gli altri personaggi vengono ignorati.
/usr/bin/cat
) per quanto riguarda la completezza di Turing?