CJam, 33 32 20 19 17 bajtów
Zmieniona wersja, z ogromną obsługą @ Sp3000 i @ MartinBüttner:
qN/_z]{:e`z,3<}/|
Wypróbuj online
Składki
- @ Sp3000 zasugerował krytyczne uproszczenie mojego oryginalnego algorytmu.
- @ MartinBüttner zastosował swoje szalone umiejętności gry w golfa w zmienionym podejściu, co prawie na pewno zaowocowało krótszym kodem, niż wymyśliłbym nawet po rozważeniu uproszczenia.
Algorytm i dowód
Poniżej wyjaśniono kryteria układania puzzli w poziomie. Przypadek pionowy można określić, patrząc na kolumny zamiast wierszy lub transponując matrycę znaków i ponownie patrząc na rzędy.
Użyję terminu „stretch” dla maksymalnej sekwencji tych samych liter. Na przykład następujące rzędy mają odpowiednio 1, 2 i 3 odcinki:
AAAAAAAA
BBBAAAAA
AABBBAAA
Użyję również terminu „blokowane” dla rzędu / układanki, które nie mogą się rozsuwać.
Kluczową obserwacją jest to, że łamigłówka może się rozsuwać, tylko wtedy, gdy wszystkie rzędy mają co najwyżej 2 odcinki . Lub odwrotnie, jest blokowany wtedy i tylko wtedy, gdy jest jakiś rząd z więcej niż 2 odcinkami .
Poniższe może nie kwalifikować się jako ścisły dowód matematyczny, ale uważam, że stanowi to przekonujące wyjaśnienie, dlaczego tak się dzieje.
Łatwo zauważyć, że układanka jest zablokowana, jeśli ma rzędy dłuższe niż 2 odcinki. Patrząc na wiersz z 3 odcinkami:
BBBAAB
jasne jest, że zapobiega to rozkładaniu się puzzli, ponieważ A
odcinek jest zablokowany między B
odcinkami. Oznacza to, że rząd jest zablokowany, co z kolei powoduje, że cała łamigłówka jest zablokowana.
Odwrotny kierunek dowodu nie jest tak oczywisty. Musimy pokazać, że nie ma powiązanych ze sobą łamigłówek, w których wszystkie rzędy mają tylko 1 lub 2 odcinki. Zaczynając od kilku obserwacji:
- Rzędy o tylko 1 odcinku nie przyczyniają się do blokowania łamigłówki, ponieważ mogą przesuwać się w dowolnym kierunku bez kolizji.
- Jeśli wszystkie rzędy z 2 odcinkami mają tę samą kolejność
A
i B
, łamigłówka wyraźnie nie jest zablokowana. W takim przypadku wszystkie A
komórki są pozostawione ze wszystkich B
komórek lub odwrotnie, i nie ma kolizji podczas rozsuwania dwóch kawałków.
Jedynym trudnym przypadkiem byłyby puzzle, w których mamy rzędy z 2 odcinkami o różnej kolejności. Pokażę, że takie łamigłówki nie istnieją w podanych specyfikacjach. Aby to pokazać, spójrzmy na częściową układankę, która ma tę konfigurację, w której .
znajdują się symbole wieloznaczne:
.......
AAABBBB
.......
BBAAAAA
.......
Teraz specyfikacja mówi, że obie komórki A
i B
są po prostu połączone we wszystkie ważne łamigłówki. Aby połączyć A
komórki w powyższej częściowej układance, mamy dwie opcje:
Pętlimy wokół jednego z odcinków B
, na przykład:
..AAAAAA
AAABBBBA
.......A
BBAAAAAA
........
Aby to zrobić, nieuchronnie przedłużamy jeden z rzędów, aby miał 3 odcinki, więc nigdy nie da nam to prawidłowej układanki, w której wszystkie rzędy mają maksymalnie 2 odcinki.
Łączymy je na bezpośredniej ścieżce:
.......
AAABBBB
..A....
BBAAAAA
.......
Te A
komórki są teraz po prostu podłączyć i nadal istnieją żadne wiersze z więcej niż 2 odcinkach. Jednak B
komórki również muszą być po prostu połączone. Bezpośrednia ścieżka jest teraz blokowana przez połączone A
komórki, a jedynym sposobem na połączenie B
komórek jest pętla wokół jednego z odcinków A
komórek. Prowadzi to z powrotem do przypadku 1, w którym nie możemy tego zrobić bez tworzenia rzędów 3 odcinków.
Aby policzyć odcinki, implementacja używa operatora CLEJ RLE.
Objaśnienie kodu
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.