>>>>>+>,[>++++++[-<-------->]<+>,]<[-[█<█<]++++++++++<]>[-]>>██[>█>>█>]+[<]<<[<]>█<<+>>[>]█>[>]█+[<]<<[<]>-█>]>>[->]<[-[[<]<]++++++++++<]>[-]>[<█]>]>[>]<[[█]<]<<<<<[<]<<██>>[>]<█[->+<]<█>>[>]<[-[[<]<]++++++++++<]>███>[<<]>[[[>]>████[<]<[-[[<]<]++++++++++<]>[-]>[█<]>]>[>]<[[-]>+[>]<-<[<]<]+<<<<<[<]>[[>]+[[>]>]>[>]>[-<+>]<[<]<[>+[<]>>-<<<<<[[<]<]>>███████>[[█]>]<]<[[<]<]<[█]>]>>>[[>]<->>]]>[[>]>]<<[[[█]<]<]<<<[█]<<█>>>[>]█[-[[<]<]++++++++++<]>>[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>]>[>]+[------->++<]>++.++.---------.++++.--------.
>>>>>+>,[>++++++[-<-------->]<+>,]<[-[[<]<]++++++++++<]>[-]>>[[[>]>>[>]+[<]<<[<]>[<<+>>[>]>>[>]<+[<]<<[<]>-]>]>>[->]<[-[[<]<]++++++++++<]>[-]>[<<]>]>[>]<[[-]<]<<<<<[<]<<[>>>[>]<[[->+<]<]>>[>]<[-[[<]<]++++++++++<]>[-]>[<<]>[[[>]>[>]+[<]<[-[[<]<]++++++++++<]>[-]>[<<]>]>[>]<[[-]>+[>]<-<[<]<]+<<<<<[<]>[[>]+[[>]>]>[>]>[-<+>]<[<]<[>+[<]>>-<<<<<[[<]<]>>[[-]+>]>[[>]>]<]<[[<]<]<[<]>]>>>[[>]<->>]]>[[>]>]<<[[[-]<]<]<<<[<]<<]>>>[>]<[-[[<]<]++++++++++<]>>[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>]>[>]+[------->++<]>++.++.---------.++++.--------.
Provalo online!
Questo implementa il setaccio di Eratostene.
L'iniziale >>>>>+>,[>++++++[-<-------->]<+>,]
inserisce ciascuna cifra come un codice carattere e sottrae 47 per metterlo nell'intervallo 1-10. Ciò consente a un valore di cella 0 di indicare la spaziatura tra i numeri. L' +>
inizio vicino di questa sezione impone che il numero sia di almeno due cifre, il che sarà presto importante.
Successivamente, e una delle prime cose che ho capito, è la sezione <[-[[<]<]++++++++++<]>[-]>
. Questo appare più volte nel codice, ognuno con differenti schemi di redazione, ma non era difficile indovinare che tutte quelle istanze erano probabilmente lo stesso codice. Questo codice richiede tre zeri a sinistra del numero decimale sul nastro e il suo effetto è di ridurre il numero. L'ultima iterazione del ciclo metterà il valore 10 due celle a sinistra del numero, ma lo [-]
pulisce.
Se il numero decimale era 0, non viene creato alcun 10 estraneo e la cella azzerata da [-]
è la cifra più significativa. La testina si trova quindi sulla seconda cifra più significativa (motivo per cui sono necessarie almeno due cifre). La maggior parte delle istanze di questo frammento sono immediatamente seguite da [<<]>
, il che pone la testa su una cella diversa da zero in condizioni normali e una cella zero se il numero decimale originale era zero. Sembra che in questo programma, la rappresentazione decimale di n-1
sia usata per denotare n
, in modo che il decremento 0
sia catturato invece che decrementare -1
.
La parte successiva inserisce i numeri da n-1 (n) a 0 (1) sul nastro:
>[ until the number reaches zero:
[ for each digit:
[>]>>[>]+[<]<<[<]> create a placeholder for the next copy
[ while the original value of the digit is nonzero:
<<+ add 1 to copy two cells left (to keep one copy)
>>[>]>>[>]<+ go to new copy and increment that cell
[<]<<[<]>- go back to original digit and decrement
] (this is effectively the same as [<+>>+<-] but with the cells at variable locations)
>] next digit
>>[->] cancel the placeholder 1s that were used for the new copy
<[-[[<]<]++++++++++<]>[-]>[<<]> decrement
]
>[>]<[[-]<] clean up the trash 10s on the tape while ending at a known location relative to the last number
Ora, questi numeri sono tutti sul nastro con due celle zero che li separano. <<<<<[<]<<
ci mette nella cella finale del penultimo numero sul nastro, che è dove saremo in ogni iterazione del ciclo. Il ciclo termina quando sono stati gestiti tutti i numeri tranne l'originale.
All'inizio del ciclo, spostiamo il numero corrente (l'ultimo ancora sul nastro) di una cella a destra per avere spazio per diminuire, quindi proseguiamo e diminuiamo:
[>>>[>]<[[->+<]<]>>[>]<[-[[<]<]++++++++++<]>[-]>[<<]>
Se questo decremento non è insufficiente, si procede a convertire il numero in unario:
[[[>]>[>]+[<]<[-[[<]<]++++++++++<]>[-]>[<<]>]
Si noti che questo frammento ha un non chiuso [
. Di conseguenza, il resto di questo ciclo viene ignorato se il numero era 0 (che rappresenta 1). Dopo la conversione in unario, cancelliamo i 10 rimanenti, trascinando la rappresentazione unaria con noi a sinistra:
>[>]<[[-]>+[>]<-<[<]<]+
Non me ne sono accorto fino a ora scrivendo questo, ma +
alla fine di questo frammento è separato dalla rappresentazione unaria da un singolo 0. Fa anche parte della rappresentazione unaria: la sequenza 1011...11
rappresenterà 0 mod k. Quanto segue <<<<<[<]>
ci mette all'inizio del numero k+1
, iniziando un nuovo ciclo.
Il ciclo interno qui "segna" ogni numero sul nastro con un 1 sulla cella immediatamente a destra, e usa la rappresentazione unaria come un orologio per determinare di quali numeri sono multipli k
.
[
[>]+ mark the current decimal number
[[>]>] move to end of decimal part of tape
>[>] move to 0 in middle of unary "clock"
>[-<+>] move the following 1 to the left if possible
<[<]< if a 1 was moved this will bring us back to a zero before the start of this "clock";
otherwise the looped move command doesn't move us at all and we are at the final 1
[ if there was no gap (happens every kth iteration):
>+[<]>>- reset to original position
<<<<<[[<]<]>> go to number that was just marked
[[-]+>] replace digits with 0s (cell value 1)
>[[>]>]< go back to where we would be without this conditional
]
<[[<]<]<[<]> return to first unmarked number
]
In [[-]+>]
quella sezione è stata l'ultima parte che ho capito. Prima di allora, ho pensato che il programma stesse facendo divisioni di prova, ma non riuscivo a vedere dove fosse usato il risultato.
Questo loop termina due celle a sinistra del numero all'estrema sinistra, >>>[[>]<->>]]
rimuove i marker posizionati sul nastro e ci riporta nuovamente alla fine del nastro. Dopodiché >[[>]>]<<[[[-]<]<]
rimuove l'orologio unario o, se questo intero segmento è stato ignorato, i rimanenti 10s. Il loop è impostato alla sua condizione iniziale con <<<[<]<<]
.
Dopo questo è solo leggendo se il numero di input è stato sostituito da 1 in qualsiasi momento:
>>>[>]<[-[[<]<]++++++++++<]>> do the check
[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>] conditionally print "not "
>[>]+[------->++<]>++.++.---------.++++.--------. unconditionally print "prime"
Fortunatamente, l'output effettivo non è stato affatto redatto.