>>>>>+>,[>++++++[-<-------->]<+>,]<[-[█<█<]++++++++++<]>[-]>>██[>█>>█>]+[<]<<[<]>█<<+>>[>]█>[>]█+[<]<<[<]>-█>]>>[->]<[-[[<]<]++++++++++<]>[-]>[<█]>]>[>]<[[█]<]<<<<<[<]<<██>>[>]<█[->+<]<█>>[>]<[-[[<]<]++++++++++<]>███>[<<]>[[[>]>████[<]<[-[[<]<]++++++++++<]>[-]>[█<]>]>[>]<[[-]>+[>]<-<[<]<]+<<<<<[<]>[[>]+[[>]>]>[>]>[-<+>]<[<]<[>+[<]>>-<<<<<[[<]<]>>███████>[[█]>]<]<[[<]<]<[█]>]>>>[[>]<->>]]>[[>]>]<<[[[█]<]<]<<<[█]<<█>>>[>]█[-[[<]<]++++++++++<]>>[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>]>[>]+[------->++<]>++.++.---------.++++.--------.
>>>>>+>,[>++++++[-<-------->]<+>,]<[-[[<]<]++++++++++<]>[-]>>[[[>]>>[>]+[<]<<[<]>[<<+>>[>]>>[>]<+[<]<<[<]>-]>]>>[->]<[-[[<]<]++++++++++<]>[-]>[<<]>]>[>]<[[-]<]<<<<<[<]<<[>>>[>]<[[->+<]<]>>[>]<[-[[<]<]++++++++++<]>[-]>[<<]>[[[>]>[>]+[<]<[-[[<]<]++++++++++<]>[-]>[<<]>]>[>]<[[-]>+[>]<-<[<]<]+<<<<<[<]>[[>]+[[>]>]>[>]>[-<+>]<[<]<[>+[<]>>-<<<<<[[<]<]>>[[-]+>]>[[>]>]<]<[[<]<]<[<]>]>>>[[>]<->>]]>[[>]>]<<[[[-]<]<]<<<[<]<<]>>>[>]<[-[[<]<]++++++++++<]>>[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>]>[>]+[------->++<]>++.++.---------.++++.--------.
Probieren Sie es online aus!
Dies implementiert das Sieb von Eratosthenes.
Der Anfang gibt >>>>>+>,[>++++++[-<-------->]<+>,]
jede Ziffer als Zeichencode ein und subtrahiert 47, um sie in den Bereich von 1 bis 10 zu bringen. Dies ermöglicht einen Zellenwert von 0, um den Abstand zwischen Zahlen anzuzeigen. Am +>
Anfang dieses Abschnitts wird die Zahl auf mindestens zwei Ziffern festgelegt, was in Kürze wichtig sein wird.
Als nächstes und eines der ersten Dinge, die ich herausgefunden habe, ist der Abschnitt <[-[[<]<]++++++++++<]>[-]>
. Dies erscheint mehrmals im Code, jedes mit unterschiedlichen Redaktionsmustern, aber es war nicht schwer zu erraten, dass alle diese Instanzen wahrscheinlich der gleiche Code waren. Dieser Code erfordert drei Nullen links von der Dezimalzahl auf dem Band, und seine Wirkung besteht darin, die Zahl zu dekrementieren. Die letzte Iteration der Schleife setzt den Wert 10 zwei Zellen links von der Zahl, aber die [-]
bereinigt ihn.
Wenn die Dezimalzahl 0 war, wird keine fremde 10 erstellt, und die durch Null gesetzte Zelle [-]
ist die höchstwertige Ziffer. Der Bandkopf befindet sich dann an der zweithöchsten Stelle (weshalb mindestens zwei Stellen erforderlich sind). Auf die meisten Instanzen dieses Snippets folgt sofort [<<]>
, wodurch der Kopf unter normalen Bedingungen auf eine Zelle ungleich Null und eine Nullzelle gelegt wird, wenn die ursprüngliche Dezimalzahl Null war. Es scheint, dass in diesem Programm die Dezimaldarstellung von n-1
verwendet wird, um zu bezeichnen n
, so dass das Dekrementieren auf 0
gefangen wird, anstatt auf dekrementiert zu werden -1
.
Der nächste Teil schreibt die Zahlen von n-1 (n) bis 0 (1) auf das Band:
>[ 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
Diese Zahlen befinden sich nun alle auf dem Band, wobei zwei Nullzellen sie trennen. <<<<<[<]<<
bringt uns in die letzte Zelle der vorletzten Nummer auf dem Band, wo wir uns in jeder Iteration der Schleife befinden werden. Die Schleife wird beendet, wenn alle Nummern außer dem Original verarbeitet wurden.
Zu Beginn der Schleife verschieben wir die aktuelle Nummer (die letzte noch auf dem Band) um eine Zelle nach rechts, um Platz zum Dekrementieren zu haben, und fahren dann fort und dekrementieren:
[>>>[>]<[[->+<]<]>>[>]<[-[[<]<]++++++++++<]>[-]>[<<]>
Wenn dieses Dekrement nicht unterlaufen ist, konvertieren wir die Zahl in unär:
[[[>]>[>]+[<]<[-[[<]<]++++++++++<]>[-]>[<<]>]
Beachten Sie, dass dieser Ausschnitt eine nicht geschlossene hat [
. Infolgedessen wird der Rest dieser Schleife übersprungen, wenn die Zahl 0 war (was 1 darstellt). Nach der Konvertierung in unary räumen wir die verbleibenden 10s aus und ziehen die unary-Darstellung mit nach links:
>[>]<[[-]>+[>]<-<[<]<]+
Ich habe es bis jetzt nicht bemerkt, aber das +
am Ende dieses Snippets ist durch eine einzelne 0 von der unären Darstellung getrennt. Es ist auch ein Teil der unären Darstellung: Die Sequenz 1011...11
wird 0 mod k darstellen. Das Folgende <<<<<[<]>
bringt uns an den Anfang der Zahl k+1
und startet eine neue Schleife.
Die innere Schleife "markiert" hier jede Zahl auf dem Band mit einer 1 in der Zelle unmittelbar rechts und verwendet die unäre Darstellung als Uhr, um zu bestimmen, welche Zahlen Vielfache von sind 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
]
Das [[-]+>]
in diesem Abschnitt war der letzte Teil, den ich herausgefunden habe. Vorher nahm ich an, dass das Programm nur Testabteilungen durchführte, aber ich konnte nicht sehen, wo das Ergebnis verwendet wurde.
Diese Schleife beendet zwei Zellen links von der ganz linken Zahl, >>>[[>]<->>]]
entfernt die auf dem Band platzierten Markierungen und bringt uns wieder zum Ende des Bandes. Danach >[[>]>]<<[[[-]<]<]
wird entweder die unäre Uhr oder, wenn dieses gesamte Segment übersprungen wurde, die übrig gebliebenen 10s entfernt. Die Schleife wird mit auf ihren Startzustand gesetzt <<<[<]<<]
.
Danach wird nur noch gelesen, ob die eingegebene Nummer zu irgendeinem Zeitpunkt durch 1 ersetzt wurde:
>>>[>]<[-[[<]<]++++++++++<]>> do the check
[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>] conditionally print "not "
>[>]+[------->++<]>++.++.---------.++++.--------. unconditionally print "prime"
Glücklicherweise wurde die tatsächliche Ausgabe überhaupt nicht redigiert.