Twoje zadanie
.. to zrobić to, czego Brian Fantana najwyraźniej nie mógł zrobić, i rozwiązać Kostkę Rubika 2x2x2.
Układ
- - A B - - - -
- - C D - - - -
E F G H I J K L
M N O P Q R S T
- - U V - - - -
- - W X - - - -
I zostanie ci przekazany przez stdin lub wiersz poleceń (twój wybór - proszę podać w odpowiedzi) w formacie:
ABCDEFGHIJKLMNOPQRSTUVWX
Należy pamiętać, że AD tworzą twarz U (w górę), EFMN tworzą twarz L (po lewej), GHOP tworzą twarz F (przednia), IJQR tworzą twarz R (po prawej), KLST tworzą Twarz B (tył) i UX tworzą twarz D (dół).
Będzie sześć unikatowych znaków reprezentujących każdy kolor, ale mogą się one różnić, więc przygotuj się na dowolną kombinację 6 znaków ascii dla każdego koloru.
Dane techniczne
- Twój kod powinien wypisywać rozwiązanie, używając tylko prawej (R), górnej (U) i przedniej (F) powierzchni, i powinien używać standardowej notacji: R, R ', R2, U, U', U2, F, F „, F2. Więcej informacji znajdziesz tutaj . Ograniczenie do podzbioru RUF jest standardowe dla kostki 2x2 (Wskazówka: traktuj dolny lewy tylny róg jako stałą podstawę do pracy).
- Twój kod musi być w stanie rozwiązać wszystkie możliwe permutacje kieszeni.
- Każde rozwiązanie powinno zająć mniej niż 30 sekund.
- Każde rozwiązanie powinno mieć mniej niż 30 ruchów.
- Bonus w wysokości -20% zostanie przyznany za rozwiązania zawsze zapewniające odpowiedzi mniejsze niż 20 ruchów (prosimy o zareklamowanie go w swojej odpowiedzi, abym mógł go dokładnie sprawdzić)
- Bonus w wysokości -50% zostanie przyznany kodowi, który zawsze zapewnia optymalne rozwiązanie. - Ponownie, prosimy o reklamę w swojej odpowiedzi
- Rozwiązania nie mogą zawierać dwóch kolejnych ruchów na tej samej twarzy, ponieważ można je łatwo połączyć w jeden ruch.
- Rozwiązania mogą opcjonalnie zawierać pojedynczą spację - i tylko jedną spację - między każdym ruchem.
- W razie potrzeby cała sekwencja rozwiązania może być zawarta w nawiasach, cudzysłowach, nawiasach klamrowych, nawiasach lub znakach kreskowych, ale żadne inne dane wyjściowe nie są dozwolone.
- Proszę podać krótko skomentowaną wersję kodu lub dokładne wyjaśnienie kodu.
- Bez użycia plików zewnętrznych. Obejmuje to Internet, tabele danych oraz biblioteki / pakiety stworzone dla tego rodzaju problemów.
- Wygrywa najkrótszy kod bajtowy.
- Zwycięzca wybrany w środę (30 lipca 2014 r.).
code-golf
puzzle-solver
permutations
rubiks-cube
Kyle McCormick
źródło
źródło
Odpowiedzi:
Python 2.7: 544 bajtów -50% = 272 bajtów **
Stackexchange zastępuje tabulatory wieloma białymi spacjami. Technicznie ta wersja ma 549 bajtów. Wystarczy zamienić pierwsze dwie spacje w wierszach 6-10 na tabulator.
Pomysł na mój program: Moim pierwszym pomysłem było pierwsze tchnienie. Ale to trwało zbyt długo. Około 2 minut na twardą (optymalną dla 11 ruchów) walkę. Postanowiłem więc podejść do problemu z obu stron. Używam dwóch zestawów. Generuję kolejno wszystkie stany o odległości 1,2,3, ... do szyfrowania i zapisuję je w zestawie 1, a jednocześnie wszystkie stany o odległości 1,2,3, ... do stanu rozwiązanego i zapisuję je w zestawie 2. Gdy stan znajduje się w obu zestawach po raz pierwszy, znaleźliśmy rozwiązanie.
W tym celu potrzebuję kolorów rozwiązanej kostki, które nie są znane. Znaki 13, 20 i 23 określają lewy, tylny i dolny kolor. Ale te 3 kolory są wystarczające do przedstawienia sześcianu. Po prostu zastępuję pozostałe 3 kolory białymi spacjami i mogę przedstawić mój rozwiązany stan jako „____ll____bbll____dddd”.
Aha, i do skrócenia permutacji skorzystałem z pomysłu z /codegolf//a/34651/29577
Wersja bez golfa:
Jestem całkiem zadowolony z wyniku, ponieważ jestem całkiem nowy w Pythonie. Jest to jeden z moich pierwszych programów w języku Python.
edycja: pół roku później: 427 - 50% = 213,5
Mam trochę więcej doświadczenia w Pythonie i golfie. Więc poprawiłem swój oryginalny kod i mogłem zapisać ponad 100 znaków.
Zasadniczo używam dokładnie tego samego podejścia. Największą zmianą jest to, że nie definiuję już funkcji. Zamiast
mogę zrobić
Również nieco zmieniłem ruch Lamdy. Najpierw skróć, a następnie bezpośrednio zintegruj kod, ponieważ wywołanie funkcji pojawia się tylko raz.
Dla każdego stanu przechowuję listę liczb od 0 do 11, aby reprezentować ruchy, zamiast ciągu zawierającego ruchy. Liczby są konwertowane na samym końcu.
Również połączyłem dwie pętle for
'for k in r(3):for j in r(3):
w jednąfor y in r(12)
. Dlatego też muszę wykonywać ruchyU4, R4, F4
. Oczywiście taki ruch nie pojawia się w najkrótszym rozwiązaniu, więc" 2'"[x%4]
działa. (Jeślix % 4 == 3
byłby wyjątek poza zakresem indeksu)Jest również trochę szybszy, ponieważ szukam wpisu w drugim zestawie wcześniej. Około 0,5 sekundy dla rozwiązania z 11 ruchami.
źródło
C, 366 - 50% premii optymalnej = 183
Korzystając z rekurencji, program przeszukuje drzewo o głębokości do 11 ruchów (maksymalna długość optymalnego rozwiązania według http://en.wikipedia.org/wiki/Pocket_Cube i strony wymienionej poniżej) i kiedy znajduje rozwiązanie wypisuje go (do 22 znaków, śledzone przez argument funkcji
m
). Zastosowana kolejność jest rodzajem słownika, w którym wszystkie trasy rozpoczynające się na U, U2, U 'są przeszukiwane przed przeszukaniem jakichkolwiek tras rozpoczynających się na R lub F. Dlatego niekoniecznie musi najpierw znaleźć optymalne rozwiązanie.Gdy rozwiązanie jest drukowane,
r
jest ono równe,m
co zapewnia, że później zostaną wydrukowane tylko równe lub krótsze rozwiązania. Umieszczenier=m-2
kosztuje dodatkowe 2 znaki, ale zapewnia wydruk tylko jednego rozwiązania dla każdej znalezionej długości (do optymalnej). Jeśli chcesz, aby wyświetlało TYLKO optymalne rozwiązanie, najlepsze rozwiązanie znalezione do tej pory musi być zapisane w zmiennej, a optymalne rozwiązanie wydrukowane na końcu programu (kosztowałoby to dodatkowe 15 znaków).dane wejściowe są wczytywane do tablicy
c[]
począwszy od indeksu 64. Jest to konieczne, aby używać w alfabecie znaków alfabetu. Symbole@
przelotoweW
są używane zamiast pytania od A do X, ponieważ konieczne jest rozpoczęcie od liczby parzystej, aby test rozwiązań działał.c['Z']
służy również do tymczasowego przechowywania, ponieważ do wykonania 4-krotnego obrotu potrzebnych jest w sumie 5 zadań. Ponieważ pierwsza częśćc[]
jest nieużywana, można przechowywać rozwiązanie (które jest zakończone bajtem zerowym, podobnie jak wszystkie ciągi C.)for(i..)
przechodzi przez sekwencję 4 ćwierć obrotu twarzy określoną przezn
.Pierwszy
for(j..)
dokonuje faktycznej zamiany zgodnie z tabeląt[]
.Aby sprawdzić, czy sześcian został rozwiązany, należy tylko sprawdzić cztery powierzchnie boczne. Elementy URF i DFR można rozróżnić nawet po usunięciu naklejek U i D, ponieważ jeden kawałek odczytuje XRF w kierunku zgodnym z ruchem wskazówek zegara, a drugi XFR. Jeśli dwa elementy zostaną zamienione, tak aby U wyświetlał się na dolnej powierzchni i odwrotnie, kolor F pojawi się na prawej twarzy i odwrotnie.
Drugi
for(j..)
liczy liczbę niedopasowań na czterech ścianach bocznych. Na przykład dla przedniej powierzchni porównuje G & O, H & P i G & H (dwa razy). Jeślie
== 0, sześcian jest rozwiązany. Jeślie
<9 lube
<13, możliwe jest rozwiązanie sześcianu odpowiednio w następnym ruchu lub 2 ruchach. W przeciwnym razie zdecydowanie nie da się rozwiązać sześcianu w tej liczbie ruchów. Aby zaoszczędzić czas, ta heurystyka służy do przycinania drzewa wyszukiwania i unikania marnowania czasu na wiele gałęzi o głębokości 10 lub 11, które się nie powiodą. Wyrażone jako formuła, staje sięe<45-m*2
.Kod niepoznany
Występ
Program został przetestowany ze wzorami od 1 do 13 na stronie http://www.jaapsch.net/puzzles/cube2.htm
Poniższe wyniki podają czas na moim komputerze, aby znaleźć WSZYSTKIE optymalne rozwiązania (dla ciekawskich). Również w przypadku bardziej złożonych pozycji czas jest podany dla wspomnianej powyżej 2-bajtowej modyfikacji, która znajduje tylko jedno optymalne rozwiązanie. W tym celu podano zarówno czas znalezienia pierwszego rozwiązania, jak i zakończenia programu. Podane rozwiązania (które zasadniczo różnią się od rozwiązań uzyskanych przez odwrócenie generatorów na połączonej stronie) zostały zweryfikowane za pomocą internetowego symulatora kostki.
źródło