Napisz najkrótszy program, który rozwiązuje kostkę Rubika (3 * 3 * 3) w rozsądnym czasie i porusza się (powiedzmy, maks. 5 sekund na twoim komputerze i mniej niż 1000 ruchów).
Dane wejściowe mają format:
UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
(to konkretne wejście reprezentuje rozwiązany moduł).
Pierwsze 12 2-znakowych ciągów to krawędzie w pozycjach UF, UR, ... BL (U = góra, F = przód, R = prawo, B = tył, L = lewy, D = dół), a następnie kolejne 8 Ciągi 3 znaków to rogi w pozycjach UFR, URB, ... DBR.
Dane wyjściowe powinny zawierać sekwencję ruchów w tym formacie:
D+ L2 U+ F+ D+ L+ D+ F+ U- F+
Gdzie D1 lub D + oznacza obrócenie powierzchni D (w dół) o 90 stopni w kierunku zgodnym z ruchem wskazówek zegara, L2 obraca powierzchnię L o 180 stopni, U3 lub U- oznacza obrócenie powierzchni U w kierunku przeciwnym do ruchu wskazówek zegara o 90 stopni.
Litery nie uwzględniają wielkości liter, a spacje są opcjonalne.
Na przykład powyższe dane wyjściowe są poprawne dla następujących danych wejściowych:
RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU
Aby uzyskać więcej informacji, zapoznaj się z konkursem kostki Tomasa Rokickiego , z wyjątkiem tego, że ocena będzie dokonywana bezpośrednio według rozmiaru pliku, jak normalny problem z golfem. Tester Internecie wliczone jest zbyt.
Dla porównania, najkrótszym już napisanym rozwiązaniem jest ostatni wpis na liście zwycięzców konkursu kostki
Dla tych, którzy mają problemy z wizualizacją formatu układu:
0-1 2-3 4-5 6-7 8-9 10-11 12-13 14-15 16-17 18-19 20-21 22-23 24-25-26 27-28-29 30-31-32 33-34-35 36-37-38 39-40-41 42-43-44 45-46-47
UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR
Front:
+-------+-------+-------+
/ / / /|
/ 30 / 4 / 27 / |
+-------+-------+-------+ |
/ / / /|28+
/ 6 / / 2 / | /|
+-------+-------+-------+ |/ |
/ / / /|3 + |
/ 33 / 0 / 24 / | /|21+
+-------+-------+-------+ |/ | /|
| | | |26+ |/ |
| 35 | 1 | 25 | /| + |
| | | |/ | /|47+
+-------+-------+-------+ |/ | /
| | | |17+ |/
| 18 | | 16 | /|11+
| | | |/ | /
+-------+-------+-------+ |/
| | | |37+
| 40 | 9 | 38 | /
| | | |/
+-------+-------+-------+
Hidden faces:
+-------+-------+-------+
/| | | |
/ | 31 | 5 | 29 |
+ | | | |
/|32+-------+-------+-------+
/ | /| | | |
+ |/ | 22 | | 20 |
/|7 + | | | |
/ | /|23+-------+-------+-------+
+ |/ | /| | | |
|34+ |/ | 44 | 13 | 46 |
| /| + | | | |
|/ | /|43+-------+-------+-------+
+ |/ | / / / /
|19+ |/ 42 / 12 / 45 /
| /|15+-------+-------+-------+
|/ | / / / /
+ |/ 14 / / 10 /
|41+-------+-------+-------+
| / / / /
|/ 39 / 8 / 36 /
+-------+-------+-------+
źródło
Odpowiedzi:
C ++ - 1123
Ponieważ jak dotąd nikt nie opublikował żadnej odpowiedzi, postanowiłem uprościć moje rozwiązanie z 2004 roku. Nadal jest daleko w tyle za najkrótszą, o której wspomniałem w pytaniu.
To nie jest przypadkowe, ale też nie przebiega prosto. Najpierw rozwiązuje krawędzie, a następnie rogi. Na każdym kroku wypróbowuje różne kombinacje maksymalnie 4 algorytmów i prostych zakrętów twarzy (sekwencyjnie, nie losowo), aż znajdzie poprawę liczby rozwiązanych elementów, a następnie powtarza się do rozwiązania. Wykorzystuje 2 algorytmy dla krawędzi i 2 dla narożników, przetłumaczone na wszystkie pozycje kostki.
Przykładowe dane wyjściowe dla
RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU
:L2F3B2F3B1U3F1B3R2F3B1U3F1B3D2F2L3D2L1U2B1L1R3U2R1L3B1U2R1U2L1F1B3U2B1F3L1U2L3R1D3L1R3B2L3R1D3L1R3L3R1D3L1R3B2L3R1D3L1R3B3F1D3B1F3R2B3F1D3B1F3U2F3L3R1B3L1R3U2L3R1B3L1R3F1D2F1L1R3D2R1L3F1D2F3L2U1B1F3L2F1B3U1L2R3L1F3R1L3U2R3L1F3R1L3U1F2U1L1R3F2R1L3U1F2U3L3U3L1U3L3U2L1R1U1R3U1R1U2R3F3U3F1U3F3U2F1B1U1B3U1B1U2B3L1B3R3B1L3B3R1B1B3D3B1D3B3D2B1F1D1F3D1F1D2F3R1F3L3F1R3F3L1F1R3B3R1B3R3B2R1L1B1L3B1L1B2L3R1D3L3D1R3D3L1D1B3D3B1D3B3D2B1F1D1F3D1F1D2F3U3R3U1R3U3R2U1D1R1D3R1D1R2D3
(234 ruchy, tutaj 0.3 sekundy)
źródło
Python 1166 bajtów
Znaczna ilość białych znaków została pozostawiona ze względu na czytelność. Wielkość mierzona po usunięciu tej spacje i zmieniając różne poziomy wcięć do
Tab
,Tab
Space
,Tab
Tab
, itd. Mam również unikać jakichkolwiek golfa co wpłynęło na wydajność zbyt drastycznie.Przykładowe użycie:
Jest to implementacja algorytmu Thistlethwaite, wykorzystująca wyszukiwanie IDA * do rozwiązania dla każdego kroku. Ponieważ wszystkie tabele heurystyczne muszą być obliczane w locie, dokonano kilku kompromisów, zwykle dzieląc heurystykę na dwie lub więcej dość równych części. To sprawia, że obliczenia tabel heurystycznych są setki razy szybsze, a jednocześnie spowalniają fazę wyszukiwania, zwykle tylko nieznacznie, ale może być znacząca w zależności od początkowego stanu kostki.
Indeks zmienny
T
- główny stół heurystyczny.S
- rozwiązany stan kostki. Każdy pojedynczy element jest przechowywany jako maska bitowa, reprezentowana jako postać. Rozwiązany wektor orientacji jest zdefiniowany jako wektor zerowy.I
- różne zwroty akcji, w kolejności, w jakiej są usuwane z przestrzeni wyszukiwania.G
- grupy permutacji skrętnych, przechowywane jako pary do zamiany. Każdy bajt w skompresowanym ciągu koduje jedną parę. Każdy zwrot wymaga sześciu zamian: trzech dla cyklu krawędzi i trzech dla cyklu narożnego. Skompresowany ciąg zawiera tylko ascii do wydruku (znaki od 32 do 126).M
- funkcja, która wykonuje ruch, nadana przez G.N
- konwertuje permutację czterech obiektów na liczbę w celu kodowania.H
- oblicza wartość heurystyczną dla danego stanu kostki, używaną do wyszukiwania głębokości ruchu z T.P
- wykonać wyszukiwanie na jednej głębokości pojedynczej fazy algorytmu.s
- stan permutacji kostki wejściowej.o
- wektor orientacji sześcianu wejściowego.Wydajność
Korzystając ze zbioru danych Tomasa Rokickiego , skrypt ten uśredniał średnio 16,02 skrętu na rozwiązanie (maksymalnie 35), przy średnim czasie 472 ms (procesor i5-3330 przy 3,0 Ghz, PyPy 1.9.0). Minimalny czas rozwiązania wynosił 233 ms, maksymalnie 2,97 s, odchylenie standardowe 0,488. Przy zastosowaniu wytycznych punktacji z konkursu (białe znaki nie są liczone, słowa kluczowe i identyfikatory liczone są jako jeden bajt o długości 870), ogólny wynik wyniósłby 13,549.
W ostatnich 46 przypadkach (stany losowe) uśredniono 30,83 skrętów na rozwiązanie, przy średnim czasie wynoszącym 721 ms.
Uwagi na temat algorytmu Thistlethwaite
Dla korzyści każdego, kto może chcieć wdrożyć algorytm Thistlethwaite , oto krótkie wyjaśnienie.
Algorytm działa na bardzo prostej zasadzie redukcji przestrzeni rozwiązania. Oznacza to, że zredukuj sześcian do stanu, w którym podzbiór skrętów nie jest konieczny do jego rozwiązania, zredukuj go do mniejszej przestrzeni rozwiązania, a następnie rozwiązuj resztę, używając tylko kilku pozostałych skrętów.
Thistlethwaite pierwotnie sugerował
<L,R,F,B,U,D>
→<L,R,F,B,U2,D2>
→<L,R,F2,B2,U2,D2>
→<L2,R2,F2,B2,U2,D2>
. Jednak biorąc pod uwagę format wejściowy, myślę, że łatwiej jest najpierw zredukować do<L,R,F2,B2,U,D>
(nie ćwierć obrotuF
lubB
), a następnie<L2,R2,F2,B2,U,D>
, zanim ostatecznie osiągając stan pół skrętu. Zamiast dokładnie wyjaśniać, dlaczego tak jest, myślę, że stanie się to oczywiste po zdefiniowaniu kryteriów dla każdego stanu.<L,R,F,B,U,D>
⇒<L,R,F2,B2,U,D>
Aby wyeliminować
F
iB
ćwierć obrotu, tylko krawędzie muszą być odpowiednio ustawione. Gilles Roux ma bardzo dobre wyjaśnienie na swojej stronie, czym jest „poprawna” i „niepoprawna” orientacja, więc wyjaśnię mu to. Ale w zasadzie, (i dlatego ten format wejściowy jest więc dysponujące naF
iB
eliminacja), cubie krawędź jest poprawnie zorientowany jeśli pasuje następujące wyrażenia regularnego:[^RL][^UD]
. Prawidłowa orientacja jest zwykle oznaczana przez a,0
a niepoprawna przez1
. ZasadniczoU
iD
nalepki nie może znajdować się naR
alboL
twarzy lub na krawędziach żadnejU
lubD
krawędzi cubies lub nie mogą być przeniesione do miejsca, bez koniecznościF
lubB
ćwierć obrotu.<L,R,F2,B2,U,D>
⇒<L2,R2,F2,B2,U,D>
Tutaj dwa kryteria. Po pierwsze, wszystkie narożniki muszą być odpowiednio ustawione, a po drugie, każde z myślą o średnich cubies warstwa (
FR
,FL
,BR
,BL
) musi być gdzieś w środkowej warstwie. Orientacja narożnika jest bardzo prosta, biorąc pod uwagę format wejściowy: położenie pierwszegoU
lubD
. Na przykładURB
ma orientację0
(poprawnie zorientowaną),LDF
ma orientację1
iLFU
ma orientację2
.<L2,R2,F2,B2,U,D>
⇒<L2,R2,F2,B2,U2,D2>
Kryteria są następujące: każda twarz może zawierać tylko naklejki z jej twarzy lub z twarzy bezpośrednio naprzeciwko. Na przykład, na
U
twarzy nie może być tylkoU
iD
naklejki naR
twarzy może być tylkoR
iL
naklejki naF
twarzy może być tylkoF
iB
naklejki itp Najprostszym sposobem zapewnienia tego jest, aby sprawdzić, czy każdy kawałek jest w krawędź jego „plasterek” i każdy narożny element na „orbicie”. Ponadto należy zwrócić uwagę na parytet narożny. Chociaż, jeśli sprawdzasz tylko parzystość narożnika, parzystość krawędzi jest również gwarantowana i odwrotnie.Jak zwroty wpływają na orientację
U
aD
skręty nie wpływają ani na orientację krawędzi, ani na orientację narożną. Kawałki mogą być zamieniane bezpośrednio bez aktualizacji wektora orientacji.R
iL
skręty nie wpływają na orientację krawędzi, ale wpływają na orientację narożnika. W zależności od tego, jak zdefiniujesz swój cykl, zmiana orientacji narożnika będzie albo,+1, +2, +1, +2
albo+2, +1, +2, +1
cały modulo3
. Należy pamiętać, żeR2
iL2
skręty nie wpływają na orientację rożnego, jak+1+2
jest zero modulo3
, jak jest+2+1
.F
iB
wpływają zarówno na orientacje krawędzi, jak i orientacje narożników. Orientacje krawędzi stają się+1, +1, +1, +1
(mod 2), a orientacje narożników są takie same jak dlaR
iL
. Należy pamiętać, żeF2
iB2
wpływa ani kierunki krawędzi, ani orientacje rożny.źródło
<L,R,F,B,U,D>
-><L2,R2,F2,B2,U,D>
-><I>
. Wymaga maksymalnie 29 zwrotów akcji, aby rozwiązać sześcian (zamiast 52 dla Thistlethwaite), ale wymaga również bardzo dużych tabel odnośników, których generowanie „w locie” byłoby niepraktyczne.Ruby, 742 znaków
Powyższy kod ruby nie jest jeszcze w pełni zagrany w golfa. Nadal istnieją możliwości dalszej poprawy kodu (ale już wystarcza jako starter).
Rozwiązuje kostkę warstwa po warstwie, ale nie używa żadnego konkretnego algorytmu, ale zamiast tego wykonuje losowe sekwencje ruchów, aż kostka zostanie rozwiązana.
Ze względu na charakter probabilistyczny rozwiązanie kostki może czasem potrwać dłużej niż 5 sekund, aw rzadkich przypadkach może zająć więcej niż 1000 ruchów.
Przykładowy wynik (dla wejścia „RU LF UB DR DL BL UL FU BD RF BR FD LDF LBD FUL RFD UFR RDB UBL RBU”) wynosi 757 ruchów:
Możliwe jest znaczne zmniejszenie liczby ruchów, jeśli te same ruchy zostaną zgrupowane razem. Dlatego można zastąpić dane wyjściowe jak
źródło
FU FR RU BR DB LD LU LB LF RD DF BU FRU BUR FDR DLB DFL LUB FUL DBR
U1 U1 U1
w jedenU3
?