BrainF ** k, 396 391 Bytes
>+>>++++[-<++++++++>]->,----------[++++++++++.>>++++++++[-<++++<------>>]<.,----------]-<+[-<+]->>+[-<<<<<++++++++++.[-]>[-<+>>.<]<[->+<]>+>>>[[->+]->>+<<<+[-<+]->]>+[-<->[[->+]->+>>+<<<<+[-<+]->]<+>->+[->+]->>[->+<]>+>++++++++++>>-<<[-<-[>>]<]<->>>+[-<<<+>>>[-<->]<+++++++++>>>+]++++++++[-<++++<++++++>>]<<<[-<<<<+[-<+]-<+>>+[->+]->>>>+<]>.>.[-]<[-]<<<[->+<]<<+[-<+]>+]>>[-]<<<-<+[-<+]->>+]
Ich konnte der Versuchung nicht widerstehen, dies zu tun. Zumindest ist das Dreieck spitz nach unten.
Die Eingabe erfolgt in Form einer Folge von numerischen Zeichen, gefolgt von einer einzelnen neuen Zeile.
Die Ausgabe enthält in jeder Zeile ein einzelnes Leerzeichen.
Beispiele:
$ bf sd.bf
010
0 1 0
1 1
2
$ bf sd.bf
123456
1 2 3 4 5 6
3 5 7 9 1
8 2 6 0
0 8 6
8 4
2
$ bf sd.bf
9245322
9 2 4 5 3 2 2
1 6 9 8 5 4
7 5 7 3 9
2 2 0 2
4 2 2
6 4
0
Erläuterung
Da es ziemlich schwierig ist, den Code aus funktionaler Sicht zu erklären, können wir ihn stattdessen zu verschiedenen Zeiten aus der Perspektive des Bandzustands betrachten. Die Kernidee dabei ist, dass das von uns ausgegebene Dreieck als dicht gepacktes Array (jedenfalls für BF) initialisiert wird, dessen Größe bei jeder Iteration einer Schleife um 1 verringert wird. Ein weiterer wichtiger Gedanke ist, dass wir 255
einen "Platzhalter" angeben, nach dem wir auf dem Band suchen können.
Initialisierung
Dies ist der einfachste Schritt. Zu Beginn des Programms führen wir Folgendes aus:
>+>>++++[-<++++++++>]->
Dadurch wird das Band in den folgenden Zustand versetzt (wobei >N<
die Position des Zeigers auf dem Band angegeben wird).
[ 0 1 32 255 >0< 0 0 ...]
Die erste Zahl ist hier ein "Puffer" -Standort. Wir werden es nicht langfristig verwenden, aber es ist nützlich, um kleine Operationen zu vereinfachen und Daten zu kopieren.
Die zweite Zahl gibt die Anzahl der Leerzeichen an, die am Anfang jeder Zeile ausgegeben werden, beginnend nach der ersten Zeile. Die erste Zeile enthält keine führenden Leerzeichen.
Die dritte Zahl ist das von uns ausgegebene Leerzeichen.
Die vierte Zahl ist ein Platzhalter 255, so dass wir relativ leicht zu dieser Position zurückkehren können.
Eingang
Von dieser Position aus werden wir alle Zeichen einlesen. Am Ende dieses Schritts hoffen wir, in der folgenden Situation zu sein:
[ 0 1 32 255 a b c d e f ... >255< 0 0 ... ]
Wobei a b c d e f ...
die eingegebene numerische Zeichenfolge angibt (nicht die Newline).
Dies erreichen wir mit:
,----------[++++++++++.>>++++++++[-<++++<------>>]<.,----------]-
Das hat einige Nuancen. Zunächst geben wir jedes Zeichen so aus, wie wir es erhalten, und geben danach ein Leerzeichen aus. Zweitens möchten wir den ASCII-Wert nicht auf das Band kopieren, sondern die tatsächliche numerische Ziffer. Drittens möchten wir aufhören, wenn wir eine neue Zeile treffen, und uns zu dieser Zeit an einem guten Ort zurücklassen.
Sagen wir, unser Input ist 6723
. Beim ersten Lesen 6
sieht unser Band dann so aus:
[ 0 1 32 255 >54< 0 0 ...]
Wir überprüfen, dass dieser Wert nicht gleich 10
(eine ASCII-Newline) mit ist ,----------[++++++++++
. Wir drucken dann den Wert aus und fahren fort, indem wir gleichzeitig 48 vom Eingabewert subtrahieren und 32 zum Wert daneben addieren ( >>++++++++[-<++++<------>>]<
). So bleiben wir hier:
[ 0 1 32 255 6 >32< 0 ...]
Beachten Sie, dass wir während dieses Vorgangs davon ausgehen können, dass alle Ziffern rechts von unserer Eingabe 0 sind. Dies bedeutet, dass wir nicht in Gefahr sind, einen vorherigen Zustand zu ruinieren, wenn wir Werte rechts von 6 * 8
und verwenden 4 * 8
.
Jetzt geben wir das soeben erzeugte Leerzeichen aus und nehmen eine neue Eingabe vor, wobei wir das dort berechnete Leerzeichen löschen. Schließlich wird die Eingabe durch eine neue Zeile beendet und die Schleife wird beendet, wobei eine Stelle verbleibt, 255
an der sich die neue Zeile befunden hätte ( ,----------]-
). Dies ist das zweite Platzhalterzeichen, mit dem wir durch das Band navigieren. An diesem Punkt in unserem Szenario ist unser Band genau das:
[ 0 1 32 255 6 7 2 3 >255< 0 0 ... ]
Berechnung
Auf diese Weise wird die Liste der Ziffern zwischen unseren 255
Platzhaltern bei jeder Wiederholung der Schleife um eins verkleinert. Wenn nur noch eine Ziffer übrig ist, sind wir fertig und sollten sofort anhalten. (Beachten Sie, dass zu diesem Zeitpunkt jede Ziffer in dieser Liste bereits ausgegeben wurde, sodass wir uns nicht mehr darum kümmern müssen, sie erneut auszugeben.)
Wir verwenden nun diesen Trick navigate auf den ersten 255
Platzhalter: <+[-<+]-
. Dadurch wird das Band auf der linken Seite effektiv nach a durchsucht 255
und nichts dazwischen geändert. Nachdem wir den Zeiger bewegt haben, können wir unsere Ausgangsbedingung überprüfen: Wenn die Liste nur eine Ziffer enthält, wird die Zelle mit den zwei Leerzeichen rechts angezeigt 255
. Also prüfen wir das und starten eine Schleife:>>+[-<<
Der erste Schritt in unserer Schleife ist die Ausgabe einer neuen Zeile. Also gehen wir zur ersten Zelle (unserer Pufferzelle), addieren 10 und geben sie aus. Der nächste Schritt ist die Ausgabe aller führenden Leerzeichen. Nach der Ausgabe erhöhen wir unsere Anzahl für die Anzahl der führenden Leerzeichen. Diese Schritte werden folgendermaßen ausgeführt:
-<<<<<++++++++++.[-]>[-<+>>.<]<[->+<]>+>>>
Was uns in diesem Zustand lässt:
[ 0 2 32 255 >6< 7 2 3 255 0 0 0 0 0 0 ]
Der nächste Schritt besteht darin, den ersten Wert in der Liste nach dem zweiten Platzhalter zu kopieren 255
:
[[->+]->>+<<<+[-<+]->]
Wir tun dies im Wesentlichen 255
, indem wir zwischen unseren Platzhaltern hin und her springen und uns hier zurücklassen:
[ 0 2 32 255 >0< 7 2 3 255 0 6 0 0 ... ]
Wir starten jetzt eine Schleife, die den Rest der Liste durchläuft und anhält, wenn wir Folgendes erreichen 255
:>+[-<
Zu diesem Zeitpunkt ist die Ziffer links von uns immer 0. Da wir sie also lieben, fügen wir dort einen Platzhalter 255
ein, damit wir zu unserem Platz in der Liste zurückkehren können. Der nächste Schritt besteht darin, den zweiten Platz in der Liste hinter den zweiten Platzhalter zu verschieben 255
. Diese Schritte werden folgendermaßen ausgeführt:
->
[[->+]->+>>+<<<<+[-<+]->]
Lassen Sie uns hier: [ 0 2 32 255 255 >0< 2 3 255 7 6 7 0 ]
Nun wurden sowohl das 6
als 7
auch an einen Ort verschoben, an dem die Berechnung erfolgen kann. Wir benötigen zwei Kopien der, 7
da die nächste Nummer in der Liste diese ebenfalls benötigt. Das 7
unmittelbar nach dem 255
dient diesem Zweck, während das andere 7
von der Berechnung verbraucht wird.
Zuerst addieren wir die beiden Ziffern:
<+>->+[->+]->>
[->+<]>
Verlassen uns hier:
[ 0 2 32 255 0 255 2 3 255 7 0 >13< 0 ]
Die nächste Kombination von Schritten ist die komplizierteste. Wir müssen sehen, ob die Zahl, auf die wir zeigen, größer als 10 ist, und wenn ja, subtrahieren wir 10
. In Wirklichkeit subtrahieren wir 10 davon und sehen, ob es 0
an einem beliebigen Punkt der Subtraktion anschlägt. In diesem Fall werden wir 10
später darauf zurückkommen. Am Ende sollten wir die Summe modulo 10 haben.
Prepare a 10 to the right
+>++++++++++
Leave yet another 255 for a loop condition later
>>-<<
If the number is greater than 10 end up one space to the left
else one space to the right
[-<-[>>]<]<->
Check if the previous 255 is two spaces to the right and if it is
add 10 back to our sum--we've subtracted too much
>>+[-<<<+>>>[-<->]<+++++++++>>>+]
Zu diesem Zeitpunkt haben wir das Ziel erreicht. Wir haben die Summe Modulo 10! Unabhängig davon, ob die Zahl größer als 10 war oder nicht, landen wir hier:
[ 0 2 32 255 0 255 2 3 255 7 0 3 0 0 >0< ]
Unser nächstes Ziel ist es, diese neue Summe auszugeben, mit einem Leerzeichen zu versehen und sie wieder in unsere Liste aufzunehmen. Wir machen das alles mit unseren bisherigen Techniken des 255
-Hoppens und Addierens 48
zu unserer Summe, deshalb werde ich nicht im Detail darauf eingehen.
++++++++[-<++++<++++++>>]
<<<[-<<<<+[-<+]-<+>>+[->+]->>>>+<]
>.>.
Und wir sind hier: [ 0 2 32 255 3 255 2 3 255 7 0 0 51 >32< ]
Beachten Sie, wie wir nach dem Einfügen einen zusätzlichen 255
Platzhalter einfügen, 3
damit wir keinen Platz in der Liste verlieren. Zu diesem Zeitpunkt haben wir unsere Summe und ihren Platz ausgegeben, daher müssen wir aufräumen und zu einem Zustand zurückkehren, in dem die nächste Iteration dieser Schleife funktionieren wird. Wir müssen unsere Zellen 51
und löschen 32
, die eine 7
nach rechts bewegen und zu unserem Listenplatzhalter navigieren, damit wir von vorne beginnen können.
[-]<[-]<<<[->+<]<<+[-<+]
Jetzt sind wir hier: [ 0 2 32 255 3 >0< 2 3 255 0 7 0 ... ]
Welches ist genau das, wo wir für unsere nächste Iteration sein wollen. Also nach 255 suchen und weitermachen! ( >+]
)
Wenn wir von der Schleife genommen werden, haben wir eine ganz neue Liste - bestehend aus den Summen der vorherigen Liste. Das erste Mal sieht es so aus:
[ 0 2 32 255 3 9 5 0 >0< ]
Jetzt wollen wir diesen ganzen Vorgang auf unserer neuen Liste wiederholen, also werfen wir einen Schritt 255
nach links und beginnen von vorne ! Wir müssen ein bisschen aufräumen >>[-]<<
und dann unseren Platzhalter mit löschen <-
. Danach befinden wir uns genau an der gleichen Stelle wie nach der Eingabe, sodass wir die gleichen Überprüfungen durchführen können:, <+[-<+]->>+
und boom! Wir haben unsere volle Schleife! Alles , was wir brauchen , ist der Schließbügel und wann es endet wir haben schon alles ausgeben, so sind wir fertig: ]
.