Istnieje wariant dobrze znanego problemu N-królowych, który dotyczy królowych i rycerzy i jest uważany za „znacznie trudniejszy” 1 . Opis problemu jest następujący:
Musisz umieścić taką samą liczbę rycerzy ♞ i królowych ♛ na szachownicy, aby żaden pionek nie atakował żadnego innego pionka. Jaką maksymalną liczbę elementów możesz umieścić na planszy i ile różnych sposobów możesz to zrobić?
W tym wyzwaniu golfowym otrzymasz n od 3 do 32 (w sposób najbardziej odpowiedni dla twojego języka). Dla danego n może istnieć zero lub więcej rozwiązań powyższego problemu. Jeśli nie ma rozwiązania, musisz nic nie wyświetlać / zwracać ( zero , pusty ciąg , fałsz , ...). W przeciwnym razie musisz podać dwa wyniki:
- Plansza rozwiązania (patrz poniżej) dla rozmiaru n, gdzie nie jest możliwe dodanie szachowej królowej lub rycerza bez atakowania żadnego pionka. Musi być równa liczba królowych i rycerzy .
- Źródło programu do uruchomienia, który nie przyjmuje danych wejściowych i daje (i) inne rozwiązanie (lub nic ) dla tego samego rozmiaru n , w tym samym formacie, a także (ii) inny program dla następnego rozwiązania (i tak dalej) ...)
Uwaga:
- Sekwencja programów nigdy nie może zwrócić tej samej płyty dwukrotnie, musi obejmować wszystkie możliwe rozwiązania problemu rozmiaru n i ostatecznie musi się zakończyć (nie generując żadnych danych wyjściowych).
- Możesz zwrócić dwie wartości, zwrócić jedną i wydrukować drugą lub wydrukować dwie zwracane wartości.
- jednak , jeśli drukować zarówno płytę i następny program, zarząd nie może być uważany za część następnego programu (polecam drukowania płytę w komentarzu, lub użyć zarówno standardowe strumienie wyjścia i błędów).
- Program jako wartość zwrotna musi być łańcuchem, a nie zamknięciem.
Format planszy
- Tablica ma kwadratowy rozmiar n .
- Komórka planszowa może być pusta, królowa lub rycerz.
- Musisz wybrać odrębne wartości dla każdego rodzaju komórek (tzn. Możesz użyć innych symboli niż Q, N podczas drukowania płytki).
- Jeśli zwrócisz tablicę niesznurkową, musi to być uporządkowany zbiór n 2 wartości planszy (np. Macierz, wektor lub lista w kolejności rzędów / kolumn, ...).
Jeśli wydrukujesz tablicę, możesz wydrukować ją w kwadracie lub w linii. Na przykład tablicę rozwiązań wielkości 4 można wydrukować w następujący sposób (spacje nie są wymagane; symbole według własnego uznania):
Q - - - - - - - - - - - - - N -
Jeśli tak uważasz, możesz także wygenerować:
♛ · · · · · · · · · · · · · ♞ ·
... ale to wystarczy:
Q-------------N-
Nie ma znaczenia, czy iterujesz przez komórki w kolejności rzędów lub kolumn, ponieważ istnieją rozwiązania symetryczne. Na przykład rozwiązania dla n = 4 to:
Q------N-------- Q----------N---- Q------------N-- Q-------------N- -Q----------N--- -Q------------N- -Q-------------N --Q---------N--- --Q----------N-- --Q------------N ---QN----------- ---Q----N------- ---Q---------N-- ---Q----------N- ---NQ----------- ----Q------N---- ----Q----------N N------Q-------- -------QN------- -------Q----N--- ---N----Q------- -------NQ------- --------Q------N N----------Q---- ----N------Q---- -----------QN--- -N----------Q--- --N---------Q--- -------N----Q--- -----------NQ--- N------------Q-- --N----------Q-- ---N---------Q-- N-------------Q- -N------------Q- ---N----------Q- -N-------------Q --N------------Q ----N----------Q --------N------Q
Możesz także spojrzeć na rozwiązania dla n = 5 jako macierzy ; deski zawiera #
, q
oraz n
symbole, które są puste komórki różnego rodzaju (patrz moją odpowiedź poniżej). Liczę 2836 plansz dla n = 6 , jak w odpowiedzi Sleafara (wprowadziłem błąd przy zmniejszaniu liczby bajtów, ale teraz jest naprawiony).
Wielkie podziękowania dla Sleafar za znalezienie nie jednego, ale dwóch błędów w moim kodzie.
Wynik
Najkrótszy kod w bajtach wygrywa.
Mierzymy rozmiar pierwszego programu, który akceptuje n .
1 . Queens and Knights , autor: Roger KW Hui (uwaga! Zawiera rozwiązanie)
-------------------------N--------Q-
jest nieprawidłowe, ponieważ można dodać więcej elementów :)Q--------N---------------N--------Q-
.Odpowiedzi:
Groovy, 515 bajtów
Testowanie
Podaj n jako argument wiersza poleceń:
Pierwszy wiersz wyniku jest zawsze rozwiązaniem jako komentarz (0 = pusty, 1 = królowa, 2 = rycerz), po którym następuje kod w drugim wierszu:
Do automatycznego testowania można użyć następującego skryptu (ponownie wprowadź n jako argument):
Ponieważ starałem się, aby rozwiązanie było jak najmniejsze, jest bardzo wolne (szczegóły poniżej). Testowałem tylko n = 4 z tą wersją, aby sprawdzić, czy quineification działa.
Wyniki
n = 4: 40 rozwiązań ( przekonwertowany format )
n = 5: 172 rozwiązań ( przekonwertowany format )
n = 6: 2836 rozwiązań ( przekonwertowany format )
Algorytm
To jest nieco nieprzyzwyczajenia nie-quine wersja rozwiązania:
Quineification
Zastosowałem tutaj bardzo proste podejście, aby utrzymać niski rozmiar kodu.
Zmienna X przechowuje indeks rozwiązania do wydrukowania w następnej kolejności. Y przechowuje zmodyfikowaną kopię powyższego algorytmu, która służy do obliczenia wszystkich rozwiązań, a następnie wybrania tylko jednego z nich, co jest przyczyną tak powolnego działania. Zaletą tego rozwiązania jest to, że nie wymaga dużo dodatkowego kodu. Kod przechowywany w Y jest wykonywany za pomocą klasy Eval (prawda quine nie jest wymagana).
Zmodyfikowany kod drukuje rozwiązanie wskazane przez X , zwiększa X i dołącza swoją kopię:
Próbowałem też wypisać wszystkie rozwiązania jako kod dla drugiego kroku, ale dla n = 6 produkowało zbyt dużo kodu, aby Groovy mógł sobie z tym poradzić.
źródło
Common Lisp, 737
odpowiedź własna
Przykład
Wklej powyższe w REPL, która zwraca obiekt funkcji:
Zadzwoń (gwiazda jest przypisana do ostatniej zwróconej wartości):
Spowoduje to wydrukowanie na standardowym wyjściu:
Ponadto wartość zwracana przez tę funkcję to:
... który jest dosłownie tablicą. Liczba 5 reprezentuje królowe, 6 oznacza rycerzy, a wszystko inne oznacza pustą komórkę, z wyjątkiem tego, że więcej informacji jest przechowywanych wewnętrznie. Jeśli skopiujemy i wkleimy zwróconą funkcję do repliki, otrzymamy nową funkcję.
I możemy to nazwać bez argumentów:
To wywołanie zwraca nowe rozwiązanie
#(5 0 0 0 0 0 0 2 0 0 0 6 0 0 2 0)
i źródło innej funkcji (nie pokazano tutaj). W przypadku gdy funkcja oryginalna lub ostatnio wygenerowana nie znajdzie rozwiązania, nic nie jest drukowane i nic nie jest zwracane.Wartości wewnętrzne
Wygenerowałem zbyt mało rozwiązań. Teraz propaguję niezależnie, która komórka jest bezpieczna dla królowej i rycerza. Na przykład, oto wynik dla n = 5 z ładnym drukowaniem:
Kiedy umieściliśmy królową
Q
, pozycje, które są ruchem rycerza od tej królowej, są nadal bezpieczne dla królowych i oznaczoneq
. Podobnie rycerze, do których dostęp mają tylko królowe, są bezpieczni dla innych rycerzy. Wartości są bitowe i -ed reprezentują możliwe ruchy, a niektóre komórki są osiągalne bez żadnego elementu.Dokładniej, oto sekwencja tablic prowadząca do następującego rozwiązania (od lewej do prawej), w którym wolne komórki są stopniowo ograniczane różnymi wartościami:
Podejście inne niż quine
Wersja bez komentarza
Duplikaty i błędy
Moje pierwsze rozwiązanie wygenerowało zduplikowane rozwiązania. Aby to rozwiązać, wprowadziłem dwa liczniki dla królowych i rycerzy. Licznik królowych (lub rycerzy) śledzi pierwszą pozycję na planszy, na której istnieje królowa (lub rycerz): Dodaję królową (lub rycerza) tylko na pozycjach następujących po tej minimalnej pozycji.
Te metody uniemożliwiają mi ponowne przyjrzenie się rozwiązaniom, które zostały już znalezione w poprzednich iteracjach, ponieważ iteruję z rosnącą pozycją królowej (lub rycerza).
Sleafar zauważył jednak, że istnieją rozwiązania, w których może być miejsce dla królowych i rycerzy, co jest niezgodne z zasadami. Przez chwilę myślałem, że muszę wrócić do normalnego wyszukiwania i przechowywać wszystkie znane rozwiązania, aby zapobiec duplikatom, co wydawało się zbyt kosztowne (zarówno pod względem bajtów, jak i użycia pamięci).
Zamiast tego oto, co robię teraz: kiedy zostanie znaleziona potencjalna plansza rozwiązania, próbuję dodać dokładnie jedną królową i jednego rycerza, nie biorąc pod uwagę liczników (tj. Dla wszystkich komórek na planszy). Jeśli to możliwe, obecna tablica jest duplikatem poprzedniej i odrzucam rozwiązanie.
Testy
Quine-ification
Miałem różne pomysły, aby tworzyć kolejne quiny. Najłatwiej jest prawdopodobnie wygenerować najpierw wszystkie rozwiązania jako listę ciągów znaków i napisać sekwencyjne quiny, które wyskakują z tej listy przy każdym pokoleniu. Nie wydawało się to jednak krótsze niż obecne podejście. Alternatywnie próbowałem przepisać kod rekurencyjny za pomocą niestandardowego stosu i zrzucić wszystkie zmienne stanu za każdym razem, gdy znajdę rozwiązanie; celem jest, aby następny krok mógł być przetwarzany jako kontynuacja bieżącego kroku. Być może byłoby to lepiej dostosowane do języka opartego na stosie. Obecna jest dość prosta i opiera się na zmiennych czytnika Common Lisp, które zawsze są przyjemne w użyciu.
źródło