APL (158 caratteri, punteggio = 4)
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
Sto usando Dyalog APL qui. Il numero di cicli può essere aumentato di uno aggiungendo 0
(0 seguito da uno spazio) alla fine dell'espressione e alla fine della stringa (prima '''
). La lunghezza del ciclo è (# 0's) + 1
e la lunghezza dell'espressione è 150 + 4*(cycle length))
. Supponendo che continuiamo ad aggiungere zeri per sempre, il punteggio è Limit[(150 + 4*n)/(n - 1), n -> Infinity] = 4
, dov'è n
la durata del ciclo.
Ecco un esempio con durata del ciclo = 6:
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0
0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0
192 caratteri, punteggio = 2
'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺ ⋄ a←⊃2⌷⍺ ⋄ ⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺⋄a←⊃2⌷⍺⋄⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01
A seconda dell'implementazione, un punto di errore potrebbe essere quando il numero intero con prefisso sulla stringa è troppo grande. Teoricamente, tuttavia, possiamo aggiungere un ciclo aggiungendo due caratteri: 1
a alla fine della stringa (prima '''
) e 1
a alla fine dell'intera riga.
200 caratteri, punteggio = 1
'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}91
La mia implementazione APL non ha interi di precisione illimitati per impostazione predefinita, quindi l'intero viene convertito in un float quando diventa troppo grande, causando un errore nell'output. Quindi questo è il più schizzinoso, ma teoricamente (a mano o con un interprete APL diverso), dovrebbe avere un punteggio di 1. Basta aggiungere un 1
alla fine dell'espressione e si ottiene un altro ciclo.
Panoramica (con un quine più corto)
Darò una panoramica della prima versione, perché penso che sia probabilmente la più facile da comprendere. Prima di affrontare quella versione, tuttavia, prenderemo in considerazione un semplice quine in APL :
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
Ho scoperto che uno dei modi migliori per comprendere alcune espressioni APL è guardare l'output attraverso la cascata di operatori / funzioni. Tutti gli operatori e le funzioni in APL sono associativi a destra e hanno la stessa precedenza, quindi eccola, da destra a sinistra:
'''1⌽22⍴11⍴'''
: Questa è solo una stringa letterale (un elenco di caratteri). ''
è il modo APL per sfuggire alle virgolette singole. Uscita: '1⌽22⍴11⍴'
.
11⍴'''1⌽22⍴11⍴'''
: Qui, risagomiamo ( ⍴
) la stringa per essere di lunghezza 11
. Poiché la lunghezza della stringa è inferiore a 11, viene ripetuta (ovvero 5⍴'abc'
cederebbe 'abcab'
). Uscita: '1⌽22⍴11⍴''
. Quindi ora abbiamo due virgolette alla fine: stiamo arrivando da qualche parte!
22⍴11⍴'''1⌽22⍴11⍴'''
: Allo stesso modo, ora ridisegniamo la lunghezza del nostro output precedente 22
. Uscita: '1⌽22⍴11⍴'''1⌽22⍴11⍴''
. Ci siamo quasi - dobbiamo solo spostare la prima citazione singola alla fine.
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
: Qui, ruotiamo ( ⌽
) l'elenco di caratteri di 1
. Questo sposta il primo carattere della stringa alla fine. Come altro esempio, 2⌽'abcdef'
ritorna 'cdefab'
. Uscita: 1⌽22⍴11⍴'''1⌽22⍴11⍴'''
.
Il quine rotante
Quel quine corto è la base principale per il nostro quine rotante. Ora, con questo in mente, diamo un'occhiata al nostro quine:
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
{ ... }
definisce una funzione senza nome, che è dove faremo il lavoro. Si noti che le funzioni in APL accettano un argomento destro, indicato da ⍵
, e un argomento sinistro opzionale, indicato da ⍺
(think infix). Vogliamo alimentare questa funzione sia la nostra stringa di quine sia qualcosa che ci aiuti a creare un numero arbitrario di cicli. Per rendere le cose più facili per noi stessi (e per chiunque voglia aggiungere cicli), rendiamo la stringa quine l'argomento sinistro. L'argomentazione corretta, quindi, è dove inseriamo la nostra lista di cicli. 2 o più elementi separati da uno spazio creano un elenco, quindi in questo esempio abbiamo un elenco di 2 elementi composto da a 1
e a 0
.
Possiamo vedere che la funzione sembra simile alla quine di prima. Abbiamo la stessa ...⌽...⍴...⍴...
forma di prima. Quindi va bene, almeno lo capiamo molto! Diamo approfondire l'ellissi, a cominciare tutto dopo l'ultima ⍴
: ⊃,/(~^/¨⍺=0)/⍺
.
- Come puoi vedere guardando l'esempio sopra, abbiamo il prefisso della stringa con gli 0 dal lato destro, aggiungendo uno ad ogni iterazione; ma non ci importa di quelli in questo momento. Vogliamo solo la corda!
- Innanzitutto, considera cosa c'è tra parentesi. (A proposito, si raggruppano come nella maggior parte delle altre lingue.)
⍺=0
restituisce un elenco, in questo caso, con la stessa forma di ⍺
, in cui ogni elemento in ⍺
è sostituito da un 1
se è uguale a 0
e un 0
altro. Questo viene eseguito in modo ricorsivo; quindi se abbiamo un elenco di un elenco di un elenco di caratteri, i singoli caratteri verranno testati rispetto a 0 e verrà restituito un elenco di un elenco di un elenco di valori binari.
- Quindi, se
⍺
costituito solo dalla nostra stringa, otteniamo un elenco di 0. Altrimenti, il nostro argomento di sinistra ha alcuni 0 con prefisso (ad esempio, 0 0 0 'quinestring'
), quindi è un elenco composto da 0 e un altro elenco, la nostra stringa. Quindi appare il nostro output 1 1 1 <sub-list of zeros>
.
^/¨⍺=0
: Applichiamo la funzione derivata ^/
, che riduce ( /
) usando la funzione logica AND ( ^
), a ciascun ¨
elemento ( ) di ⍺=0
. Questo per appiattire la sotto-lista di zeri in modo da poter considerare la stringa quine come un valore binario. Considerando l'esempio precedente, l'output sarebbe 1 1 1 0
.
~
: NON binari ciascuno dei valori precedenti (ad es. Ritorno 0 0 0 1
).
(~^/¨⍺=0)/⍺
: Per ogni elemento in ⍺
, lo repliciamo ( /
) il numero di volte dato dall'elemento corrispondente nell'argomento sinistro. Questo elimina tutti gli 0, lasciandoci solo con la nostra stringa quine.
⊃,/
sono alcuni documenti necessari per garantire di recuperare un elenco di caratteri appiattito, riducendo il risultato con la funzione di concatenazione ( ,
). Se l'input è già un elenco appiattito (ovvero, l'argomento sinistro della nostra funzione principale è solo la stringa), otteniamo un elenco di 1 elemento contenente tale elenco. Nell'altro caso, quando abbiamo un elenco costituito da un sotto-elenco per la stringa, otteniamo la stessa cosa indietro (un elenco con un sotto-elenco). Quindi scompattiamo questo ( ⊃
), dandoci solo il primo elemento della lista (cioè la sotto-lista di caratteri). Questo potrebbe sembrare superfluo, ma altrimenti cercheremmo di rimodellare un elenco di 1 elemento!
Successivamente, esaminiamo la lunghezza fornita per la prima modifica, tra parentesi:
⍺,⍵
: Concateniamo l'argomento giusto al primo argomento
⊃,/⍺,⍵
: Come prima - appiattisci l'elenco.
+/0=⊃,/⍺,⍵
: Consente di aggiungere il numero di zeri nell'elenco riducendo ( /
) utilizzando la funzione addition ( +
).
2×+/0=⊃,/⍺,⍵
: Moltiplica quel numero per due.
z←2×+/0=⊃,/⍺,⍵
: Assegna ( ←
) il risultato a una variabile, z
. Per ricapitolare, z
ora è il doppio del numero di zeri trovati negli argomenti sinistro e destro.
77+z←2×+/0=⊃,/⍺,⍵
: Aggiungiamo quindi 77
, per i caratteri nella stringa quine, ignorando tutto ciò che segue lo spazio seguente 1
. Come nell'esempio iniziale di Quine, aggiungiamo 1 alla lunghezza della stringa per ottenere un'altra virgoletta singola.
- L'output di questa nuova forma, in questo esempio, è:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
L'argomento alla nuova forma che segue è semplice e rispecchia la breve quina (2 volte la lunghezza della prima forma). Il nostro output ora è:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
Ora per il passaggio finale, in cui calcoliamo quanto ruotare la stringa di output:
- Come puoi vedere guardando l'output precedente, vogliamo ruotarlo indietro (un importo negativo) per portare le 2 virgolette finali all'inizio. Poiché vogliamo che anche uno
0
(e un altro spazio) si spostino all'inizio, vogliamo ruotarlo di altri 3 caratteri indietro.
+/+/¨⍺=0
: Somma il numero di zeri nell'argomento sinistro . Il primo (da destra) +/¨
somma il conteggio di ciascun elemento (ovvero, un elenco secondario o solo un numero intero), e il secondo +/
ci fornisce la somma dell'elenco risultante.
5+2×+/+/¨⍺=0
: Moltiplica per due (per ruotare anche gli spazi) e aggiungi 5 (il risultato che abbiamo trovato prima).
- Ora, sottraggiamo il valore precedente dall'argomento sinistro
-
per gestire il caso quando raggiungiamo la fine del nostro ciclo:
(3+z)×^/⍵
: E tutti gli elementi nell'argomento giusto insieme per vedere se abbiamo raggiunto il nostro fine ( 1
) e moltiplicalo per 3+z
.
E abbiamo finito!