Wenn Sie nicht wissen, was der Turm von Hanoi ist, erkläre ich es kurz: Es gibt drei Stangen und einige Scheiben, von denen jede eine andere Größe hat. Am Anfang befinden sich alle Scheiben in sortierter Reihenfolge auf dem ersten Turm: Die größte befindet sich unten, die kleinste oben. Ziel ist es, alle Scheiben auf die dritte Stange zu bringen. Klingt einfach? Hier ist der Haken: Sie können keine CD auf eine CD legen, die kleiner als die andere ist. Sie können immer nur eine Scheibe auf einmal in der Hand halten, um sie auf eine andere Stange zu bewegen, und Sie können die Scheibe nur auf Stangen legen, nicht auf den Tisch, Sie hinterhältiger Bastard.
ASCII-Beispiellösung:
A B C
| | |
_|_ | |
__|__ | |
A B C
| | |
| | |
__|__ _|_ |
A B C
| | |
| | |
| _|_ __|__
A B C
| | |
| | _|_
| | __|__
Herausforderung
Es gibt drei Stäbe mit den Bezeichnungen A, B und C. (Sie können sie auch mit 1,2 bzw. 3 bezeichnen, wenn das hilft) Am Anfang befinden sich alle n Scheiben auf Stab A (1).
Ihre Herausforderung besteht darin, eine Lösung für den Turm von Hanoi zu überprüfen. Sie müssen sicherstellen, dass:
- Am Ende befinden sich alle n Scheiben auf Stab C (3).
- Für eine bestimmte Disc in einem bestimmten Zustand befindet sich keine kleinere Disc darunter.
- Keine offensichtlichen Fehler wie der Versuch, Scheiben von einer leeren Stange zu nehmen oder Scheiben auf nicht vorhandene Stangen zu bewegen.
(Die Lösung muss nicht optimal sein.)
Eingang
Ihr Programm erhält zwei Eingaben:
- Die Anzahl der Discs n (eine ganze Zahl)
Die ausgeführten Züge, die aus einer Reihe von Tupeln bestehen: (Turm, von dem die derzeit oberste Scheibe genommen wird), (Turm, zu dem diese Scheibe genommen wird), wobei sich jedes Tupel auf einen Zug bezieht. Sie können wählen, wie sie dargestellt werden. Zum Beispiel so etwas wie die folgenden Darstellungsweisen der Lösung für n = 2, die ich oben in ASCII gezeichnet habe. (Ich werde den ersten in den Testfällen verwenden, weil es für die Augen einfach ist):
A-> B; A-> C; B-> C
[("A", "B"), ("A", "C"), ("B", "C")]
[(1,2), (1,3), (2,3)]
"ABACBC"
[1,2,1,3,2,3]
Ausgabe
Wahrheit, wenn die Bedingungen, die unter "Herausforderung" zu finden sind, gelten.
Falsch, wenn nicht.
Testfälle:
Wahr:
n=1, "A->C"
n=1, "A->B ; B->C"
n=2, "A->B ; A->C ; B->C"
n=2, "A->C ; C->B ; A->C ; B->C"
n=2, "A->C ; A->B ; C->B ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=4, "A->B ; A->C ; B->C ; A->B ; C->A ; C->B ; A->B ; A->C ; B->C ; B->A ; C->A ; B->C ; A->B ; A->C ; B->C"
Falsch:
3. Vorschlag von @MartinEnder, 7. Vorschlag von @Joffan
n=1, "A->B"
n=1, "C->A"
n=2, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=2, "A->B ; A->C ; C->B"
n=2, "A->C ; A->B ; C->B ; B->A"
n=2, "A->C ; A->C"
n=3, "A->B ; A->D; A->C ; D->C ; A->C"
n=3, "A->C ; A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->B ; B->C ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; C->B"
n=4, "A->B ; A->C ; B->C ; A->B ; C->A ; C->B ; A->B ; A->C ; B->C ; B->A ; C->A ; B->C ; A->B ; A->C"
n=4, "A->B ; A->B ; A->B ; A->C ; B->C ; B->C ; B->C"
Dies ist Code-Golf , die kürzeste Lösung gewinnt. Es gelten Standardregeln und Regelungslücken. Keine Batterien enthalten.
A=1
,B=2
,C=3
, etc.)?A->A
?moving discs to nonexistant rods.
ja natürlichD
Antworten:
Retina ,
8480 Bytes-5 Bytes dank Martin Ender
Probieren Sie es online! (plus 5 Bytes für zeilenweise Tests)
Der Code simuliert ein vollständiges Spiel.
ACABCBACBABCAC~~~
.~~~
bedeutet drei Scheiben.ACABCBACBABCAC ~~~ ~~ ~ABC
.Am Anfang hat die A-Stange alle 3 Scheiben und die B- und C-Stangen sind leer.
In out Beispiel nach dem ersten Schritt wird der Text wie folgt aussehen:
~CABCBACBABCAC ~~~ ~~ABC
.ABCBACBABCAC ~~~ ~~AB ~C
.quelle
Retina ,
167165157150123 BytesDas sieht total nach einer Herausforderung aus, die mit einem einzigen regulären Ausdruck gelöst werden sollte ... (Trotz der Überschrift "Retina" ist dies nur ein regulärer Ausdruck in Vanilla .NET, der mit gültigen Eingaben übereinstimmt).
Eingabeformat ist die Liste der Anweisungen des Formulars
AB
, gefolgt vonn
unärem Verwenden der Ziffer1
. Es gibt keine Trennzeichen. Die Ausgabe ist1
gültig und0
ungültig.Probieren Sie es online! (Die ersten beiden Zeichen ermöglichen eine durch Zeilenvorschub getrennte Testsuite.)
Alternative Lösung, gleiche Byteanzahl:
Dies kann möglicherweise durch die Verwendung verkürzt werden
1
,11
und111
stattA
,B
undC
aber ich werde später in diesem Blick haben. Es könnte auch kürzer sein, das Programm in mehrere Phasen aufzuteilen, aber wo liegt die Herausforderung dabei? ;)Erläuterung
Diese Lösung nutzt die Bilanzkreise von .NET in hohem Maße. Eine vollständige Erklärung finden Sie in meinem Beitrag zum Stapelüberlauf. Das Wesentliche ist jedoch, dass es sich bei Erfassungsgruppen in .NET um Stapel handelt, bei denen jede neue Erfassung eine andere Teilzeichenfolge überträgt und bei denen es auch möglich ist, erneut von einem solchen Stapel zu springen. Auf diese Weise können Sie verschiedene Mengen in einer Zeichenfolge zählen. In diesem Fall können wir die drei Stäbe direkt als drei verschiedene Erfassungsgruppen implementieren, wobei jede Disc durch eine Erfassung dargestellt wird.
Um die Scheiben zwischen den Stäben hin und her zu bewegen, verwenden wir eine seltsame Besonderheit der
(?<A-B>...)
Syntax. Normalerweise wird dabei ein Capture vom Stapel gezogenB
undA
die Zeichenfolge zwischen diesem Capture und dem Anfang dieser Gruppe auf den Stapel gelegt . So(?<A>a).(?<B-A>c)
abgestimmt gegenabc
verlassen würdeA
leer undB
mitb
(im Gegensatz zuc
). Aufgrund von .NET-Lookbehinds mit variabler Länge ist es jedoch möglich, dass sich die Captures von(?<A>...)
und(?<B-A>...)
überlappen. Aus welchem Grund auch immer, wenn dies der Fall ist, wird der Schnittpunkt der beiden Gruppen aufgeschobenB
. Ich habe dieses Verhalten im Abschnitt "Erweitert" über Bilanzkreise in dieser Antwort detailliert beschrieben .Auf zum Regex. Rods
A
,B
undC
entsprechen den Gruppen3
,4
und5
in dem regulären Ausdruck. Beginnen wir mit der Initialisierung von rodA
:Wenn zB die Eingabe mit endet
111
, enthält Gruppe 3 / StabA
jetzt die Liste der Captures[111, 11, 1]
(die obere befindet sich rechts).Das nächste Bit des Codes hat die folgende Struktur:
Jede Iteration dieser Schleife verarbeitet einen Befehl. Die erste Abwechslung zieht eine Scheibe von der gegebenen Stange (auf eine temporäre Gruppe), die zweite Abwechslung legt diese Scheibe auf die andere gegebene Stange. Wir werden gleich sehen, wie das funktioniert und wie wir sicherstellen, dass der Umzug gültig ist.
Nehmen Sie zuerst eine Disc von der Source-Stange:
Dies verwendet das seltsame Gruppenschnittverhalten, das ich oben beschrieben habe. Beachten Sie, dass Gruppe
3
,4
und5
immer halten Strings1
s am Ende der Zeichenfolge , deren Länge entspricht die Größe der Scheibe. Wir verwenden nun,(?<1-N>.+)
um die obere Scheibe vom Stapel zu nehmenN
und den Schnittpunkt dieser Teilzeichenfolge mit der Übereinstimmung.+
auf den Stapel zu schieben1
. Da.+
immer zwangsläufig das gesamte Capture abgesprungen istN
, wissen wir, dass sich dadurch einfach das Capture verschiebt.Als nächstes legen wir diese Scheibe vom Stapel
1
auf den Stapel, der dem zweiten Stab entspricht:Beachten Sie, dass wir den Stapel nicht bereinigen müssen, sondern
1
die CD einfach dort lassen können, da eine neue darauf gelegt wird, bevor der Stapel erneut verwendet wird. Das heißt, wir können die(?<A-B>...)
Syntax umgehen und den String einfach mit kopieren(\1)
. Um sicherzustellen, dass der Zug gültig ist, verwenden wir den negativen Lookahead(?!\N)
. Dies stellt sicher, dass es von der Position aus, an der wir die aktuelle Disc zuordnen möchten, unmöglich ist, die bereits gestapelte Disc zuzuordnenN
. Dies kann nur passieren, wenn entweder a)\N
niemals übereinstimmt, weil der Stapel vollständig leer ist, oder b)the disc on top of stack
Nis larger than the one we're trying to match with
\ 1`.Schließlich muss nur noch sichergestellt werden, dass a) alle Anweisungen und b) die Stangen übereinstimmen
A
undB
leer sind, sodass alle Discs verschoben wurdenC
.Wir überprüfen einfach, ob weder eine Übereinstimmung
\3
noch\4
eine Übereinstimmung möglich ist (was nur der Fall ist, wenn beide leer sind, da jede tatsächliche Disc übereinstimmen würde ) und dass wir dann eine Übereinstimmung erzielen können,1
sodass wir keine Anweisungen ausgelassen haben.quelle
Java "nur"
311 272 263 261 260 259256 BytesGespeichert
39unzählige Bytes aufgrund @Frozn eine ältere Debug - Funktion sowie einige clevere Golf Tricks zu bemerken.Golf Version
ungolfed mit Erklärung und hübschen gedruckten Stapeln bei jedem Schritt
Die ungolfed-Version hat eine Funktion, mit der gedruckt wird, wie die Stapel bei jedem Schritt aussehen ...
quelle
System.out.println(Arrays.toString(s))
das?&&
mit&
.Python 2,
186167158135127115110102 BytesÜbernimmt Eingaben in STDIN im folgenden Format:
Das heißt, ein Python-Tupel der Anzahl der Disks und eine Python-Liste der Tupel von
(from_rod,to_rod)
. Wie in Python sind die umgebenden Klammern optional. Die Stäbe sind mit einem Index von Null versehen.Zum Beispiel dieser Testfall:
würde gegeben sein als:
Wenn die Lösung gültig ist, gibt nichts aus und tritt mit einem Exit - Code von 0. Wenn es ungültig ist, werfen eine Ausnahme und wird mit einem Exit - Code 1 einen Überwurf ,
IndexError
wenn auf eine nonexistant Stange zu bewegen oder versuchen , eine Scheibe aus einem zu übernehmen Stange, auf der sich keine Discs befinden, aZeroDivisionError
wenn eine Disc auf einer kleineren Disc liegt oder aNameError
wenn am Ende der ersten oder zweiten Stange noch Discs vorhanden sind.13 Bytes gespart dank @KarlKastor!
8 Bytes gespart dank @xnor!
quelle
Python 2.7,
173158138130127123 Bytes:Übernimmt die Eingabe über die Standardeingabe in dem Format,
(<Number of Discs>,<Moves>)
in dem<Moves>
sie als Array angegeben wird, das Tupel für jeden Zug enthält, die jeweils ein Paar durch Kommas getrennte Ganzzahlen enthalten. Zum Beispiel der Testfall:in der Post gegeben wäre gegeben als:
zu meinem Programm. Gibt ein aus,
IndexError
wenn die 3. Bedingung nicht erfüllt ist, ein,NameError
wenn die 2. Bedingung nicht erfüllt ist undFalse
wenn die 1. Bedingung nicht erfüllt ist. Ansonsten AusgängeTrue
.quelle
Y
wird nie in Ihrem Code definieren (denke ich , dass J sein soll) undU[J]+=[Y,[U[K].pop()]][U[J]<[1]or U[K]<U[J]]
kürzer von 3 Zeichen , dass diestmt1 if cond else stmt2
Y
Variable, um den Wert zu erhöhen,NameError
wenn die 2. Bedingung nicht erfüllt ist. Wenn ich etwas ändernY
zuJ
, dann ist dasNameError
nicht angehoben werden. Aus diesem Grund kann ich das auch nicht machen,U[J]+=[Y,[U[K].pop()]][U[J]<[1]or U[K]<U[J]]
da dies dieNameError
ganze Zeit eine erhöhen würde , nicht nur wenn die 2. Bedingung nicht erfüllt ist.VBA,
234217213196 BytesDas Eingabeformat für Züge ist eine Zeichenfolge mit einer geraden Anzahl von Ziffern (012). Der Aufruf erfolgt in der Tabelle, = H ([Anzahl der Datenträger], [Zeichenfolge verschieben])
Die Anordnung A hält die Stabposition der verschiedenen Scheiben. Ein Zug aktualisiert einfach das erste Auftreten der Stangennummer "Von" in die Stangennummer "Bis". Wenn Sie zuerst auf eine "To" -Rutenscheibe oder keine "From" -Rutenscheibe stoßen, ist dies ein ungültiger Zug. Der gesamte "Stabwert" von A wird in L gehalten, was bei 2N enden muss. Fehler werden in E negativ gezählt.
Wie bei anderen Lösungen ist das "Verschieben" einer Disc von einem Turm in den gleichen Turm nicht verboten. Ich könnte es für weitere 6 Bytes verbieten.
Ergebnisse
Funktionsergebnis in der ersten Spalte (der letzte Fall n = 3 ist meine Hinzufügung unter Verwendung eines zusätzlichen Stabes).
quelle
PHP, 141 Bytes
Befehlszeilenskript, verwendet die Eingabe als Höhe und dann eine Reihe von Array-Indizes (0 indiziert), z. B. 1 0 2 oder 2 0 1 0 2 1 2 für die kürzesten Testfälle mit 1 oder 2 Höhen.
Echos 1 über wahre Fälle und nichts über falsche.
Gibt 2 Hinweise und 1 Warnung, muss also in einer Umgebung ausgeführt werden, die diese zum Schweigen bringt.
quelle
JavaScript (ES6), 108
Eingabeformat: Funktion mit 2 Argumenten
Ausgabe: 1, wenn ok, 0, wenn ungültig, Ausnahme, wenn kein Stab vorhanden ist
Weniger golfen und erklärt
Test Hinweis: Die erste Zeile der Testfunktion wird benötigt, um das in der Frage angegebene Eingabeformat in die von meiner Funktion erwartete Eingabe zu konvertieren
quelle