Twoim celem jest napisanie idealnego gracza do gry Wythoff's Nim .
Zasady Nim Wythoffa
Wythoff's Nim to deterministyczna gra dla dwóch graczy, rozgrywana dwoma stosami identycznych znaczników. Gracze naprzemiennie tury, w których wykonują jedną z następujących czynności:
- Usuń jeden lub więcej znaczników z pierwszego stosu
- Usuń jeden lub więcej żetonów z drugiego stosu
- Usuń taką samą liczbę liczników (jeden lub więcej), zarówno z pierwszego stosu, jak i drugiego stosu.
Oczywiście stosy nie mogą być ujemne, ale mogą osiągnąć wartość 0. Niezależnie od tego, który gracz usunie ostatni licznik, wygrywa grę.
Dla bardziej nastawionych geometrycznie, oto ekwiwalent gry, w którą możesz grać za pomocą tego apletu . Jedna królowa zaczyna na jakimś kwadracie nieskończonej szachownicy, której róg znajduje się w lewym dolnym rogu. Gracze naprzemiennie poruszają królową, która porusza się jak królowa szachów, ale ogranicza się do trzech kierunków:
- Na dół
- Lewo
- Po przekątnej w dół i w lewo
Kto przenosi królową do rogu, wygrywa.
Przypisując współrzędne królowej (z rogiem (0,0)
) do rozmiarów odpowiednich stosów, łatwo jest zauważyć, że obie gry są takie same.
Idealna gra
(Możesz to pominąć, jeśli znasz pojęcia doskonałej gry i zwycięskich ruchów.)
Ponieważ Wythoff's Nim jest skończoną i deterministyczną grą, ma idealną grę . Idealny gracz to strategia, która zawsze wygrywa z teoretycznie wygranej pozycji, co oznacza pozycję, w której istnieje strategia gwarantująca zwycięstwo.
Aby być zwycięską strategią, wystarczy przejść, aby zawsze przejść do teoretycznej zwycięskiej pozycji dla gracza, który właśnie się poruszył, a tym samym gracza, który nie pójdzie dalej. Pierwsze z tych zwycięskich pozycji (zwane również pozycjami zimnymi ) to (0,0), (1,2), (2,1), (3,5), (5,3)
. Zobacz artykuł w Wikipedii, aby uzyskać wyjaśnienie algorytmu znajdowania zwycięskiej strategii dla Wythoffa Nima, a także formułę generowania zwycięskich pozycji.
Wymagania programu
Napisz program lub funkcję przyjmuje pozycję jako dane wejściowe i wyprowadza zwycięski ruch w postaci pozycji po tym ruchu. Wygrywa najmniej bajtów.
Jeśli nie ma żadnego wygrywającego ruchu, tj. Pozycja jest teoretyczną stratą, Twój program powinien to zaznaczyć i przepadnąć.
Twój program musi zostać uruchomiony w rozsądnym czasie. Zatem wykładnicze rekurencyjne wyszukiwanie drzewa gry nie wystarczy. Jeśli chcesz wstępnie obliczyć i zaprogramować strategię, nie ma sprawy.
Wejście
Para (i,j)
liczb nieujemnych reprezentujących rozmiary stosów, każda najwyżej 99
. Mogą to być dwie liczby, krotka, lista lub dowolny inny kontener.
Wynik
Wydrukuj lub wyślij pozycję po swoim ruchu, ponownie jako dwie liczby lub ich pojemnik. To musi być legalne przejście do zwycięskiej pozycji. Jeśli jest wiele takich ruchów, każdy jest w porządku, ale tylko jeden.
Jeśli nie ma zwycięskiego ruchu, musisz to wskazać w wynikach. Wszelkie wyjścia jak False
, None
, 0, lub (-1,-1)
zrobi, tak długo jak nie jest to sytuacja prawna, i jest taka sama dla każdego wejścia przegranej.
Przykład działa
f(5,0) = (0,0)
f(2,2) = (1,2) # Or (2,1) or (0,0)
f(1,2) = False
f(13,9) = (13,8) # Or (10,6)
f(10,6) = False
f(5,10) = (5,3)
f(25,30) = (8,13)
źródło
Odpowiedzi:
Haskell,
167165 znakówAlgorytm jest nieefektywny, ale nadal działa w ciągu sekundy (choć nie w interaktywnej konsoli) dla danych wejściowych <100.
Wyjaśnienie:
Lista pozycji zimnych z zestawem poprzednich pozycji zimnych to jedna pozycja zimna, a następnie lista pozycji zimnych z tą pozycją i poprzednimi (Nieskuteczność: ta pozycja jest generowana dwukrotnie)
Jedna zimna pozycja to pierwsza para, tak że nie ma dostępnych zimnych pozycji z tej pary (Nieefektywność: zamiast tego powinniśmy szukać z poprzedniej pary)
Pozycje osiągalne z pary są takie, że ich pierwsze elementy pasują, ich drugie elementy pasują, ich różnice pasują lub mniejsza sterty przed usunięciem jest większą stertą po usunięciu.
(główna metoda) Jeśli stosy są w niewłaściwej kolejności, zamień je. W przeciwnym razie, jeśli pierwszą zimną pozycją osiągalną z pozycji jest sama pozycja, wskaż awarię (najlepiej
Maybe (Int,Int)
zamiast tego powróci ). W przeciwnym razie zwróć tę zimną pozycję (Brak wydajności: wspomniana para jest dwukrotnie sprawdzana. Gorzej, lista zimnych pozycji jest generowana dwukrotnie)źródło
x@
zx@(a,b)?p=...
GolfScript (
6357 bajtów)Oczekuje danych wejściowych z wejścia standardowego w formularzu
[a b]
i pozostawia dane wyjściowe ze standardowego wejścia w tej formie lub0
jeśli jest to pozycja tracąca. Demo onlinePrzegląd
oblicza listę zimnych pozycji (w tym wersję odwróconą
[b a]
dla każdej zimnej pozycji[a b]
) przy użyciu właściwości sekwencji Beatty .Następnie
?
wyszukuje pierwszą zimną pozycję spełniającą blok utworzony przezktóre zasadniczo sprawdza, czy pozycja jest osiągalny ze stanowiska wejściowego poprzez obliczenie różnicy wektorowej, a następnie sprawdzenie, czy to albo
[0 x]
,[x 0]
albo[x x]
dla niektórychx > 0
. IMO, że test jest najmądrzejszym bitem:0|$
zmusza dowolną tablicę w jednym z tych formatów do formy[0 x]
podczas mapowania[0 0]
do[0]
,[a b]
gdzie ania
nieb
jest0
do tablicy trzech elementów, a[-x 0]
lub[-x -x]
na[-x 0]
. Następnie(!*,1=
sprawdza, które mamy[0 x]
.Wreszcie
0]0=`
jest to przypadek zastępczy i formatowanie danych wyjściowych.źródło
Pyt 57
58 61 62Wypróbuj online.
Całkiem podobne do innych odpowiedzi, ale ta strona Wikipedii nie dała wiele do zrobienia;) Magiczna liczba
39
to liczba zimnych pozycji z wartościami <99
.Definiuje funkcję
g
, którą możesz wywołaćg 30 25
. W[]
przypadku niepowodzenia zwraca się w przypadku niepowodzenia[(13,8)]
.Wyjaśnienie
źródło
s
jest rzutowany na int - zapisuje kilka znaków ponad/____1
.rZ39
może być zastąpiony przezU39
, używając jednokierunkowego zasięgu. Podobnie, można zastąpićr99)
zU99
.U
. Naprawdę powinienem zaktualizować wyjaśnienie: P@
wykonać skrzyżowanie, jeśli jego drugim argumentem jest teraz lista. Jest to trochę niezręcznie pominięte, ponieważa
zostało zmienione: PJavaScript ES6 - 280 bajtów
Zminimalizowane
Rozszerzony
Ładny i szybki algorytm. Działa w O (n), ale działałby w stałym czasie, gdyby nie pętla zapisująca bajty. Pętla została zaimplementowana jako inkrementator inkrementalny, dlatego skrypt ostatecznie zawiedzie z błędem rekurencji dla nw setkach lub tysiącach. Wykorzystuje tę samą właściwość sekwencji Beatty, o której wspomina pan Taylor, ale zamiast obliczać sekwencję, po prostu zbliża się do właściwego terminu (-ów).
Działa poprawnie na wszystkich wejściach testowych i wielu innych poza tym, co testowałem.
Funkcja do wywołania to
f
. Zwraca tablicę po sukcesie i0
po poddaniu się.źródło
Perl 5-109 (z 2 flagami)
Stosowanie:
Po prostu oblicza rozwiązanie dla każdego możliwego wejścia, a następnie wykonuje tylko jedno wyszukiwanie.
źródło