Ich dachte, ich würde diese Gelegenheit nutzen, um ein neues Retina-Feature vorzuführen: mehrstufige Loops. Dies sollte viele Aufgaben erheblich verkürzen (insbesondere den bedingten Austausch).
ii
-
+`(.)\1|0
(.)-|(\d)(\d)
-$1$3$2
12
i3
23
i1
31
i2
)`(\d)i
i$1
^\D*$
$&0
Retina ist meine eigene, auf Regex basierende Programmiersprache. Der Quellcode kann in Phasen gruppiert werden: Jede Phase besteht aus zwei Zeilen, wobei die erste die Regex (und möglicherweise eine Konfiguration) enthält und die zweite Zeile die Ersatzzeichenfolge ist. Die Stufen werden dann der Reihe nach auf STDIN angewendet, und das Endergebnis wird auf STDOUT gedruckt.
Sie können die oben genannten direkt als Quelldatei mit der -s
Befehlszeilenoption verwenden. Ich zähle den Schalter jedoch nicht, da Sie auch einfach jede Zeile in eine separate Datei einfügen können (dann verlieren Sie 15 Byte für die Zeilenumbrüche, fügen jedoch +15 für die zusätzlichen Dateien hinzu).
Erläuterung
Das Neue an dieser Lösung ist )
das vorletzte Stadium. Dies schließt eine mehrstufige Schleife. Es gibt keine Übereinstimmung (
, was bedeutet, dass die Schleife implizit in der ersten Stufe beginnt. Daher werden die ersten 7 Stufen wiederholt, bis ein vollständiger Durchlauf durch alle 7 das Ergebnis nicht mehr ändert. Diese 7 Stufen führen einfach verschiedene Transformationen durch, die die Anzahl der Matrizen in der Kette allmählich verringern und die Phasen kombinieren. Sobald wir das Endergebnis erreicht haben, stimmt keines der sieben Muster mehr überein und die Schleife endet. Danach fügen wir eine 0 hinzu, wenn das Ergebnis noch keine Ziffer enthält (da in den obigen Schritten einfach alle Identitäten einschließlich des Ergebnisses gelöscht werden).
Das machen die einzelnen Stufen:
ii
-
Kombiniert alle Paare von i
in -
, um die Phasenzeichen zu reduzieren.
+`(.)\1|0
<empty>
Wenn nun zwei aufeinanderfolgende identische Zeichen übrig sind, sind es entweder --
zwei identische Matrizen. In beiden Fällen ergibt die Multiplikation die Identität. Wir brauchen aber keine Identitäten, also entfernen wir einfach alle und auch die expliziten Identitäten 0
. Diese Phase wird in sich wiederholt, +
bis sich das Ergebnis nicht mehr ändert. Dies stellt sicher, dass Dinge wie 123321
vollständig aufgelöst werden, sodass der nächste Schritt davon ausgehen kann, dass alle Ziffernpaare unterschiedlich sind.
(.)-|(\d)(\d)
-$1$3$2
Dies sind eigentlich zwei getrennte Transformationen in einer (für Golf). Beachten Sie, dass, wenn die erste Alternative zutrifft $2
und $3
leer ist, und wenn die zweite zutrifft, $1
leer ist. Das kann also in diese zwei Schritte zerlegt werden:
(\d)(\d)
-$2$1
Dadurch werden nur alle Ziffernpaare vertauscht und ein Minuszeichen hinzugefügt. Da wir alle entfernt 0
s und alle identische Paare, wird dies nur passen 12
, 23
, 31
, 21
, 32
, 13
. Dieser Schritt mag seltsam erscheinen, aber ich kann später nur die Hälfte dieser Fälle überprüfen, da diejenigen, die ich dann nicht verarbeiten kann, in der nächsten Iteration hier ausgetauscht werden.
Der andere Teil der obigen Etappe war:
(.)-
-$1
Dadurch werden die -
Zeichen schrittweise ganz nach links verschoben (eine Position pro Iteration). Ich mache das so, dass sie letztendlich alle nebeneinander stehen und im vorherigen Schritt gelöst werden.
12
i3
23
i1
31
i2
Diese drei Stufen lösen nun einfach die drei Produktpaare auf. Wie ich oben sagte, wird dies nur die Hälfte der relevanten Fälle erfassen, aber die andere Hälfte wird in der nächsten Iteration behoben, nachdem der vorherige Schritt alle Paare vertauscht hat.
)`(\d)i
i$1
Dies ist die letzte Stufe der Schleife. Es ist ähnlich wie das, das sich -
nach links verschiebt, mit Ausnahme von i
. Der Hauptunterschied ist, dass dieser i
nur mit Ziffern vertauscht wird. Wenn ich (.)i
dann in Fällen verwendet, in denen ich ein -i
oder i-
die zwei bekomme, würde auf unbestimmte Zeit getauscht und das Programm würde nicht beendet. Das vertauscht sie also nur rechts von den -
Zeichen. Dies ist ausreichend - solange alle -
und i
zu einem bestimmten Zeitpunkt zusammen angezeigt werden, können sie korrekt aufgelöst werden.
^\D*$
$&0
Der letzte Schritt (außerhalb der Schleife). Denken Sie daran, dass wir immer alle Identitäten gelöscht haben. Wenn das Ergebnis also tatsächlich die Identität ist (mal eine Phase), haben wir die erforderliche Ziffer nicht mehr in der Ausgabe, also fügen wir sie zurück.
Als Beispiel sind hier alle Zwischenformen von 0223202330203313021301011023230323
(Überspringen von Phasen, die keine Änderungen durchführen):
0223202330203313021301011023230323
321321312 # Remove identities
-23-31-12-132 # Swap all pairs
-23-31-i3-132 # Resolve 12
-i1-31-i3-132 # Resolve 23
-i1-i2-i3-132 # Resolve 31
-i-1i-2i-3-312 # Move - to the left and swap pairs
-i-1i-2i-3-3i3 # Resolve 12
-i-i1-i2-3-i33 # Move i to the left
-i-i1-i2-3-i # Remove identities
--ii-1i-2-3i # Move - to the left
--ii-i1-2-i3 # Move i to the left
----i1-2-i3 # Resolve ii
i1-2-i3 # Remove identities
i-1-2i3 # Move - to the left
i-1-i23 # Move i to the left
-i-1i-32 # Move - to the left and swap pairs
-i-i1-32 # Move i to the left
--ii-1-23 # Move - to the left and swap pairs
--ii-1-i1 # Resolve 23
----1-i1 # Resolve ii
1-i1 # Remove identities
-1i1 # Move - to the left
-i11 # Move i to the left
-i # Remove identities. Now the loop can't change this any longer.
-i0 # Fix the result by adding in the 0.