CJam, 33 32 20 19 17 Bytes
Überarbeitete Version, mit massiver Unterstützung von @ Sp3000 und @ MartinBüttner:
qN/_z]{:e`z,3<}/|
Probieren Sie es online aus
Beiträge
- @ Sp3000 schlug eine kritische Vereinfachung meines ursprünglichen Algorithmus vor.
- @ MartinBüttner hat seine verrückten Golffähigkeiten auf die überarbeitete Herangehensweise angewendet, was mit ziemlicher Sicherheit zu einem kürzeren Code führte, als ich es mir trotz Vereinfachung ausgedacht hätte.
Algorithmus und Beweis
Im Folgenden werden die Kriterien für das horizontale Auseinandergleiten des Puzzles erläutert. Der vertikale Fall kann durch Betrachten von Spalten anstelle von Zeilen oder durch Transponieren der Zeichenmatrix und erneutes Betrachten der Zeilen bestimmt werden.
Ich werde den Begriff "Strecken" für eine maximale Folge der gleichen Buchstaben verwenden. Beispielsweise haben die folgenden Zeilen 1, 2 und 3 Abschnitte:
AAAAAAAA
BBBAAAAA
AABBBAAA
Ich werde den Begriff "Interlocked" auch für eine Reihe / ein Puzzle verwenden, die / das nicht auseinander rutschen kann.
Die Schlüsselbeobachtung ist, dass das Puzzle nur dann auseinander rutschen kann, wenn alle Reihen höchstens 2 Strecken haben . Oder umgekehrt, es ist nur dann verriegelt, wenn es eine Reihe mit mehr als 2 Abschnitten gibt .
Das Folgende könnte nicht als strenger mathematischer Beweis gelten, aber ich glaube, dass es eine überzeugende Erklärung dafür liefert, warum dies der Fall sein muss.
Es ist leicht zu erkennen, dass das Puzzle verriegelt ist, wenn es Reihen mit mehr als 2 Abschnitten enthält. Eine Reihe mit 3 Strecken betrachten:
BBBAAB
es ist klar, dass es verhindert, dass das Puzzle auseinander rutscht, da die A
Strecke zwischen den B
Strecken gesperrt ist . Dies bedeutet, dass die Reihe ineinander greift, wodurch das gesamte Puzzle ineinander greift.
Die Gegenrichtung des Beweises ist nicht ganz so offensichtlich. Wir müssen zeigen, dass es keine ineinandergreifenden Rätsel gibt, bei denen alle Reihen nur 1 oder 2 Strecken haben. Beginnen wir mit ein paar Beobachtungen:
- Reihen mit nur 1 Dehnung tragen nicht zum Ineinandergreifen eines Puzzles bei, da sie ohne Kollisionen in beide Richtungen gleiten können.
- Wenn alle Reihen mit 2 Abschnitten die gleiche Reihenfolge von
A
und haben B
, ist das Rätsel eindeutig nicht miteinander verzahnt. In diesem Fall A
bleiben alle B
Zellen von allen Zellen übrig oder umgekehrt, und es kommt zu keinen Kollisionen, wenn die beiden Teile auseinander geschoben werden.
Der einzige schwierige Fall wären Rätsel, bei denen wir Reihen mit 2 Abschnitten unterschiedlicher Reihenfolge haben. Ich werde zeigen, dass solche Rätsel unter den angegebenen Spezifikationen nicht existieren . Um dies zu zeigen, schauen wir uns ein Teilpuzzlespiel mit dieser Konfiguration an, in dem .
sich Platzhalter befinden:
.......
AAABBBB
.......
BBAAAAA
.......
Nun, sagt die Spezifikation , dass sowohl die A
und B
Zellen sind einfach in allen gültigen Puzzles verbunden. Um die A
Zellen im obigen Teilrätsel zu verbinden, haben wir zwei Möglichkeiten:
Wir umrunden einen der folgenden Abschnitte B
:
..AAAAAA
AAABBBBA
.......A
BBAAAAAA
........
Um dies zu tun, erweitern wir unvermeidlich eine der Reihen auf 3 Strecken, so dass wir niemals ein gültiges Rätsel erhalten, bei dem alle Reihen höchstens 2 Strecken haben.
Wir verbinden sie auf direktem Weg:
.......
AAABBBB
..A....
BBAAAAA
.......
Die A
Zellen sind jetzt einfach verbunden und es gibt noch keine Zeilen mit mehr als 2 Abschnitten. Die B
Zellen müssen jedoch auch einfach verbunden werden. Der direkte Pfad wird jetzt von den verbundenen A
Zellen blockiert , und die einzige Möglichkeit, die B
Zellen zu verbinden , besteht darin, eine der Zellabschnitte in einer Schleife zu A
durchlaufen. Dies führt zu Fall 1 zurück, in dem wir dies nicht tun können, ohne Zeilen mit 3 Abschnitten zu erstellen.
Zum Zählen der Strecken verwendet die Implementierung den CJam-RLE-Operator.
Erklärung des Codes
qN/ Get input and split at newlines.
_z Make a transposed copy.
] Wrap the original and transposed puzzle in an array so that we can
loop over the two.
{ Start of loop over original and transposed puzzle.
:e` Apply RLE to all rows.
z, Transpose the matrix with the RLE rows, and take the element count of the
result. Or in other words, take the column count. This will be the length
of the longest row after RLE.
3< Check the length for less than 3.
}/ End of loop over original and transposed puzzle.
| Or the results of the two.