Fueue , 423 byte
Fueue è un esolang basato sulla coda in cui il programma in esecuzione è la coda.
)$$4255%%1(~):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]](H-):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Provalo online!
Come funziona
Questa spiegazione può o non può essere sfuggita di mano. D'altra parte non so come spiegarlo molto più breve in un modo che spero che la gente possa seguire.
Fueue cheat sheet
Vedi l' articolo wiki di esolang per i dettagli, incluse le poche funzioni non utilizzate in questo programma.
Il programma iniziale è lo stato iniziale della coda, che può contenere i seguenti elementi:
- Letterali interi (solo non negativi nella fonte, ma quelli negativi possono essere calcolati), eseguendoli stampa un carattere.
- Blocchi nidificati delimitati da parentesi quadre, inerti (conservati intatti a meno che alcune funzioni non agiscano su di essi).
- Funzioni, i loro argomenti sono gli elementi che li seguono immediatamente nella coda:
+*/-%
: aritmetica intera ( -
è unaria, %
negazione logica). Argomenti numerici inerti se non indicati.
()<
: mette l'elemento tra parentesi, rimuove le parentesi dal blocco, aggiunge l'elemento finale al blocco. Gli ultimi due sono inerti a meno che non siano seguiti da un blocco.
~:
: swap, duplicato.
$
: copia (richiede il numero + elemento). Inerte prima di non numero.
H
: programma di arresto.
Nota che, mentre []
annidate, ()
non farlo - queste ultime sono semplicemente funzioni separate.
Sintassi della traccia di esecuzione
Lo spazio bianco è facoltativo in Fueue, tranne tra i numeri. Nelle seguenti tracce di esecuzione verrà utilizzato per suggerire la struttura del programma, in particolare:
- Quando viene eseguita una funzione, essa e i suoi argomenti saranno messi in risalto dagli spazi circostanti con spazi. Se alcuni degli argomenti sono complicati, potrebbe esserci anche uno spazio tra loro.
- Molte tracce di esecuzione sono divise in un "BLOB di ritardo" a sinistra, separato da una parte a destra che esegue la sostanziale manipolazione dei dati. Vedi la prossima sezione.
Le parentesi graffe {}
(non utilizzate in Fueue) vengono utilizzate nelle tracce per rappresentare il risultato intero delle espressioni matematiche. Questo include numeri negativi, poiché Fueue ha solo valori letterali non negativi - -
è la funzione di negazione.
Vari nomi metavariabili e ...
vengono utilizzati per indicare valori e abbreviazioni.
Ritardare le tattiche
Intuitivamente, l'esecuzione esegue un ciclo attorno alla coda, modificando parzialmente ciò che passa. I risultati di una funzione non possono essere nuovamente attivati fino al ciclo successivo. Diverse parti del programma si evolvono efficacemente in parallelo purché non interagiscano.
Di conseguenza, gran parte del codice è dedicato alla sincronizzazione, in particolare al ritardo nell'esecuzione di parti del programma fino al momento giusto. Ci sono molte opzioni per giocare a golf, che tende a trasformare quelle parti in macchie illeggibili che possono essere comprese solo tracciando il loro ciclo di esecuzione ciclo per ciclo.
Queste tattiche non saranno sempre menzionate individualmente nel seguito:
)[A]
ritardi A
per un ciclo. (Probabilmente il metodo più semplice e più leggibile.)
~ef
scambia gli elementi e
e f
ciò ritarda anche la loro esecuzione. (Probabilmente il meno leggibile, ma spesso il più breve per ritardi minori.)
$1e
ritarda un singolo elemento e
.
-
e %
sono utili per ritardare i numeri (quest'ultimo per 0
e 1
.)
- Quando si ritardano più elementi uguali di seguito,
:
oppure$
possono essere utilizzati per crearli da un singolo.
(n
è racchiuso n
tra parentesi, che possono essere rimosse in seguito a piacimento. Ciò è particolarmente vitale per i calcoli numerici, poiché i numeri sono troppo instabili per essere copiati senza prima metterli in un blocco.
Struttura generale
Il resto della spiegazione è diviso in sette parti, ciascuna per una sezione del programma in esecuzione. I cicli più grandi dopo i quali la maggior parte di essi si ripetono saranno chiamati "iterazioni" per distinguerli dai "cicli" dei singoli passaggi attraverso l'intera coda.
Ecco come si divide il programma iniziale tra loro:
A: )$$4255%%1(~
B: ):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
C:
D: (H-
E:
F:
G: ):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Il grande numero alla fine del programma codifica il resto al contrario, due cifre per carattere, con 30 sottratte da ciascun valore ASCII (quindi ad esempio 10
codifica un(
.)
A un livello superiore puoi pensare ai dati di questo programma (a partire dal bignum) come che scorre da destra a sinistra, ma controlla il flusso da sinistra a destra. Tuttavia, a un livello inferiore, Fueue confonde continuamente la distinzione tra codice e dati.
- La sezione G decodifica il bignum in cifre ASCII (ad es. Cifra
0
come numero intero 48
), suddividendo prima le cifre meno significative. Produce una cifra ogni 15 cicli.
- La sezione F contiene i valori ASCII della cifra prodotta (ciascuno all'interno di un blocco) fino a quando la sezione E li può consumare.
- La sezione E gestisce le cifre prodotte due alla volta, accoppiandole in blocchi del modulo
[x[y]]
, stampando anche il carattere codificato di ciascuna coppia.
- La sezione D è costituita da un blocco nidificato in profondità costruito gradualmente dai
[x[y]]
blocchi in modo tale che una volta che contenga tutte le cifre, possa essere eseguito per stamparle tutte, quindi arrestare l'intero programma.
- La sezione C gestisce la costruzione della sezione D e ricrea anche la sezione E.
- La sezione B ricrea la sezione C e se stessa ogni 30 cicli.
- La sezione A esegue il conto alla rovescia dei cicli fino all'ultima iterazione delle altre sezioni. Quindi interrompe la sezione B ed esegue la sezione D.
Sezione a
La sezione A gestisce la pianificazione della fine del programma. Sono necessari 4258 cicli per ridurre a una singola funzione di scambio ~
, che quindi effettua una regolazione alla sezione B che interrompe il suo ciclo principale e inizia invece a eseguire la sezione D.
)$ $4255% %1 (~
)$%%%...%% %0 [~]
)$%%%...% %1 [~]
⋮
)$ %0 [~]
) $1[~]
)[~]
~
- Una
$
funzione crea 4255 copie di quanto segue %
mentre racchiude (
le ~
parentesi quadre.
- Ad ogni ciclo l'ultimo
%
viene utilizzato per alternare il seguente numero tra 0
e 1
.
- Quando tutti gli
%
s sono esauriti, $1
crea 1 copia del [~]
(effettivamente un NOP), e nel ciclo successivo )
rimuove le parentesi.
Sezione B
La sezione B gestisce la rigenerazione e una nuova iterazione della sezione C ogni 30 cicli.
) : [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] [BkB]
)$ $24% %0 :< [~:)~)] ~ [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] [BkB]
)$ %...%%% %1 < < [~:)~)] [BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...%% %0 < [~:)~)[BkB]] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...% %1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
⋮
) $1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
~:) ~)[BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
) : [BkB] ) [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] (2)
) [BkB] [BkB] $11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<
- A
:
duplica il blocco grande seguente (una copia abbreviata come [BkB]
), quindi )
rimuove le parentesi dalla prima copia.
$$24%%0
imposta un conto alla rovescia simile a quello nella sezione A.
- Mentre questo fa il conto alla rovescia,
:<
si trasforma in <<
e ~
scambia due dei blocchi, posizionando il codice per una nuova sezione C per ultima.
- Le due
<
funzioni racchiudono i due blocchi finali nel primo: questo è ridondante nelle iterazioni normali, ma consentirà alla ~
sezione A di fare il suo lavoro alla fine.
- (1) Al termine del conto alla rovescia,
)
rimuove le parentesi esterne. Successivamente ~:)
si trasforma ):
e si ~)
scambia )
a all'inizio del codice della sezione C.
- (2) La sezione B è ora tornata al suo ciclo iniziale, mentre a
)
sta per rimuovere le parentesi per iniziare a eseguire una nuova iterazione della sezione C.
Nell'iterazione finale, ~
dalla sezione A appare al punto (1) sopra:
~ ) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
[~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] )
Gli ~
swap del )
tutto il blocco e nella sezione C, impedendo sezione B vengano eseguiti nuovamente.
Sezione C
La sezione C gestisce l'unione di nuove coppie di caratteri numerici nel blocco della sezione D e crea anche nuove iterazioni della sezione E.
Di seguito viene mostrata una tipica iterazione con x
e che y
rappresenta i codici ASCII delle cifre. Nella primissima iterazione, gli elementi "D" ed "E" in arrivo sono gli elementi iniziali [H]
e -
invece, poiché nessuna sezione precedente E è stata eseguita per produrre coppie di caratteri numerici.
C D E
$11~ ) ~<[[+$4--498+*-:~-10)):])<~] [)))~] < [)))~[...]] [x[y]]
~~~ ~~~ ~~~ ~~) [[+$4--498+*-:~-10)):])<~] < [)))~] [)))~[...][x[y]]]
~~~ ~~~ ) ~ [[+$4--498+*-:~-10)):])<~] [)))~[)))~[...][x[y]]]]
~~~ ~ ) [)))~[....]] [[+$4--498+*-:~-10)):])<~]
~~[)))~[....]] )[[+$4--498+*-:~-10)):])<~]
[)))~[....]] ~[+$4--498+*-:~-10)):])<~
- Questo utilizza un diverso metodo di sincronizzazione che ho scoperto per questa risposta. Quando si hanno diverse funzioni di scambio
~
in una riga, la riga si riduce a circa 2/3 di ogni ciclo (perché uno ~
scambia due successivi), ma occasionalmente con un resto di ~
s che provoca il caos manipola attentamente ciò che segue.
$11~
produce una tale riga. Il prossimo ~
scambia a <
attraverso il blocco seguente. Un altro <
alla fine aggiunge un nuovo blocco di coppie di cifre (cifre xey come codici ASCII) nel blocco sezione D.
- Il ciclo successivo, la
~
riga ha un ~~
resto, che sostituisce ~
il seguente )
. L'altro <
aggiunge la sezione D a un [)))~]
blocco.
- Successivamente lo
~
stesso swap scambia il blocco seguente con il nuovo codice della sezione E attraverso il blocco della sezione D. Quindi un nuovo avanzi ~
scambia un )
attraversamento, e infine l'ultimo ~~
nella ~
riga scambia uno di essi attraverso la sezione E proprio come )
ha rimosso le sue parentesi.
Nell'iterazione finale, la sezione A ~
ha scambiato una )
sezione trasversale B e una sezione C. Tuttavia, la sezione C ha una durata così breve che è già scomparsa, e )
finisce all'inizio della sezione D.
Sezione D
La sezione D gestisce la stampa del grande numero finale e l'arresto del programma. Durante la maggior parte dell'esecuzione del programma, è un blocco inerte che le sezioni B – G cooperano alla costruzione.
(H -
[H]-
⋮
[)))~[H-]] After one iteration of section C
⋮
[)))~[)))~[H-][49[49]]]] Second iteration, after E has also run
⋮
) [)))~[...]] [49[48]] Final printing starts as ) is swapped in
))) ~[...][49[48]]
)) )[49[48]] [...]
)) 49 [48][...] Print first 1
) )[48] [...]
) 48 [...] Print 0
)[...] Recurse to inner block
...
⋮
)[H-] Innermost block reached
H - Program halts
- Nel primo ciclo del programma, a racchiude tra parentesi la
(
funzione di arresto H
. A -
seguito, verrà utilizzato come elemento fittizio per la prima iterazione anziché una coppia di cifre.
- La prima coppia di cifre reali incorporata è
[49[49]]
, corrispondente alla finale 11
nel numero.
- L'ultima coppia di cifre
[49[48]]
(corrispondente 10
all'inizio del numero) non è effettivamente incorporata nel blocco, ma questo non fa differenza in quanto )[A[B]]
e )[A][B]
sono equivalenti, entrambi si trasformano in A[B]
.
Dopo l'iterazione finale, lo )
scambio dalla sezione B a destra arriva e il blocco della sezione D viene sbloccato. )))~
L'all'inizio di ciascun sottoblocco fa in modo che tutte le parti siano eseguite nell'ordine corretto. Infine, il blocco più interno contiene un H
arresto del programma.
Sezione E
La sezione E gestisce la combinazione di coppie di cifre ASCII prodotte dalla sezione G ed entrambe stampa il carattere codificato corrispondente e invia un blocco con la coppia combinata verso sinistra alle sezioni C e D.
Ancora una volta il seguente mostra una tipica iterazione con x
e che y
rappresenta i codici ASCII delle cifre.
E F
~ [+$4--498+*-:~-10)):] ) < ~ [y] [x]
) [+$4--498+*-:~-10)):] < [x] [y]
+ $4- - 498 +*- :~ -10 ) ) : [x[y]]
+--- -{-498} +*- ~~{-10} ) ) [x[y]] [x[y]]
+-- - 498 +* -{-10} ~ ) x [y] [x[y]]
+- -{-498} + * 10 x )[y] [x[y]]
+ - 498 + {10*x} y [x[y]]
+ {-498} {10*x+y} [x[y]]
{10*x+y-498} [x[y]]
[x[y]]
- I blocchi di cifre in entrata vengono scambiati, quindi il blocco y viene aggiunto al blocco x e l'intero blocco di coppie viene copiato. Una copia rimarrà fino alla fine per le sezioni C e D.
- L'altra copia viene nuovamente sbloccata, quindi viene applicata una sequenza di funzioni aritmetiche per calcolare
10*x+y-498
il valore ASCII del carattere codificato. 498 = 10*48+48-30
, 48
s annulla la codifica ASCII di x
e y
mentre 30
sposta la codifica da 00–99
a 30–129
, che include tutte le ASCII stampabili.
- Il numero risultante viene quindi lasciato da eseguire, che stampa il suo carattere.
Sezione F
La sezione F è costituita da blocchi inerti contenenti codici ASCII di cifre. Per la maggior parte del programma in esecuzione ce ne saranno al massimo due qui, poiché la sezione E li consuma alla stessa velocità con cui G li produce. Tuttavia, nella fase di stampa finale alcune 0
cifre ridondanti verranno raccolte qui.
[y] [x] ...
Sezione G
La sezione G gestisce la suddivisione del grande numero alla fine del programma, prima le cifre meno significative e l'invio di blocchi con i loro codici ASCII a sinistra verso le altre sezioni.
Poiché non ha alcun controllo di interruzione, continuerà effettivamente a produrre 0
cifre quando il numero si è ridotto a 0, fino a quando la sezione D interrompe l'intero programma con la H
funzione.
[BkG]
abbrevia una copia del grande blocco di codice iniziale, che viene utilizzato per l'auto-replica per avviare nuove iterazioni.
Inizializzazione nei primi cicli:
) :~ : [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ( 106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
) ~ ~ [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] [BkG] [10...11]
) [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ~ [BkG] [10...11]
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [10...11] [BkG]
Tipica iterazione, N
indica il numero da dividere:
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [N] [BkG]
) :~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+ :5 ) : [N] : [BkG]
) ~ ~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] +5 5 ) [N] [N] [BkG] [BkG]
) [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] ~ 10 N [N] [BkG] [BkG]
) ~:~ ~ ( [:~)*[):~[$1(+48]):~+]-:~~)10)~~] / N 10 [N] [BkG] [BkG]
) ~ : [:~)*[):~[$1(+48]):~+]-:~~)10)~~] ( {N/10} [N] [BkG] [BkG]
) [:~)*[):~[$1(+48]):~+]-:~~)10)~~] : [{N/10}] [N] [BkG] [BkG]
:~ )*[):~[$1(+48]):~+]- :~ ~)10 ) ~ ~ [{N/10}] [{N/10}] [N] [BkG] [BkG]
~~) *[):~[$1(+48]):~+]- ~~10 ) ) [{N/10}] ~ [{N/10}] [N] [BkG] [BkG]
) ~ * [):~[$1(+48]):~+] -10 ~ ) {N/10} [N] [{N/10}] [BkG] [BkG]
) [):~[$1(+48]):~+] * {-10} {N/10} ) [N] [{N/10}] [BkG] [BkG]
) :~ [$1(+48]) :~ + {-10*(N/10)} N [{N/10}] [BkG] [BkG]
) ~ ~ [$1(+48] ) ~ ~ {N%10} [{N/10}] [BkG] [BkG]
) [$1(+48] ~ ) {N%10} ~ [{N/10}] [BkG] [BkG]
$1( + 48 {N%10} ) [BkG] [{N/10}] [BkG]
( {48+N%10} BkG [{N/10}] [BkG] New iteration starts
[{48+N%10}] ....
- La macchia di ritardo qui è particolarmente pelosa. Tuttavia, l'unico nuovo trucco di ritardo è usare
+:5
invece di --10
ritardare 10
due cicli. Purtroppo solo uno dei 10
programmi in programma è stato aiutato da questo.
- I blocchi
[N]
e [BkG]
vengono duplicati, quindi una copia di N
viene divisa per 10
.
[{N/10}]
viene duplicato, quindi vengono utilizzate più funzioni aritmetiche per calcolare il codice ASCII dell'ultima cifra di N
as 48+((-10)*(N/10)+N)
. Il blocco con questo codice ASCII è lasciato per la sezione F.
- L'altra copia di
[{N/10}]
viene scambiata tra i [BkG]
blocchi per impostare l'inizio di una nuova iterazione.
Bonus quine (540 byte)
)$$3371%%1[~!~~!)!]):[)$$20%%0[):]~)~~[)$$12%%0[<$$7%~~0):~[+----48+*-~~10))]<]<~!:~)~~[40~[:~))~:~[)~(~~/[+--48):]~10]+30])):]]][)[H]](11(06(06(21(21(25(19(07(07(19(61(96(03(96(96(03(11(03(63(11(28(61(11(06(06(20(18(07(07(18(61(11(28(63(96(11(96(96(61(11(06(06(19(20(07(07(18(61(30(06(06(25(07(96(96(18(11(28(96(61(13(15(15(15(15(22(26(13(12(15(96(96(19(18(11(11(63(30(63(30(96(03(28(96(11(96(96(61(22(18(96(61(28(96(11(11(96(28(96(61(11(96(10(96(96(17(61(13(15(15(22(26(11(28(63(96(19(18(63(13(21(18(63(11(11(28(63(63(63(61(11(61(42(63(63
Provalo online!
Dato che non ero sicuro di quale metodo sarebbe stato il più breve, ho prima provato a codificare i caratteri come numeri a due cifre separati da (
s. Il codice principale è un po 'più breve, ma la rappresentazione dei dati più grande del 50% lo compensa. Non tanto da golf quanto l'altro, come mi sono fermato quando ho capito che non l'avrebbe battuto. Ha un vantaggio: non richiede un'implementazione con supporto bignum.
La sua struttura complessiva è in qualche modo simile a quella principale. Manca la sezione G poiché la rappresentazione dei dati riempie direttamente la sezione F. Tuttavia, la sezione E deve eseguire un calcolo divmod simile per ricostruire le cifre dei numeri a due cifre.