Ucieczka z szachownicy


23

Znajdziesz się na szachownicy, tak jak się to robi. Możesz zobaczyć wyjście, ale jest okropnie daleko i wolisz nie iść całą drogę. Na szczęście niektórzy miejscowi zaoferowali ci przejażdżkę. Rycerz, Wieża, Biskup i Król chętnie zabiorą cię do miejsca docelowego, ale widząc, jak to jest szachownica, muszą przestrzegać zasad szachowych w drodze do miejsca docelowego. Chcesz się stąd jak najszybciej wydostać, czyją ofertę akceptujesz?

Zadanie

Biorąc pod uwagę dowolnie ukształtowaną i wielkości szachownicę oraz dwa punkty na szachownicy, wyjmij pionek szachowy, który może przemieszczać się między dwoma miejscami w jak najmniejszej liczbie ruchów. Tablice niekoniecznie muszą być ciągłe, co oznacza, że ​​mogą występować przerwy między sekcjami planszy. Każdy z czterech elementów (król, wieża, rycerz i biskup) może poruszać się zgodnie z ich standardowymi zasadami w szachach. Królowa i pionki zostały celowo wykluczone z tego wyzwania.

I / O

Możesz przyjmować dane wejściowe w dowolnym rozsądnym formacie, a także dane wyjściowe w dowolnym wybranym przez siebie formacie. Twoje dane wejściowe i wyjściowe muszą być spójne. Jeśli wiele elementów może dotrzeć do celu w tej samej liczbie ruchów, musisz wydać wszystkie elementy, które mogą się tam dostać w jak najkrótszym czasie. Jeśli żaden z czterech elementów nie dotrze do końca, możesz wydać cokolwiek, o ile różni się ono od wszystkich innych możliwych wyników. Może to obejmować nie wysyłanie niczego lub zgłaszanie błędu.

Przypadki testowe

Kwadrat wskazuje punkt początkowy, a okrąg wskazuje punkt końcowy.


Test 1

Biskup


Test 2

Rycerz


Test 3

Król


Test 4

Wieża


Test 5

Król, rycerz


Test 6

Żaden


Miły. Podoba mi się to, ale czy „szachownica o dowolnym kształcie i rozmiarze” nie jest pojedynczą jednostką? Naprawdę nie rozumiem, jak pasują do tego przykłady 2 i 6, ponieważ wygląda na to, że są to dwie oddzielne plansze, między którymi tylko rycerz może przeskakiwać. Może czegoś mi brakuje?
ElPedro

2
@ElPedro Nadal są pojedynczą tablicą, to po prostu nie jest ciągła deska. Częścią dowolnego kształtu jest to, że deski mogą być nieciągłe.
Wheat Wizard

Na przykład 3, czy nie powinien to być „król, królowa”?
Kritixi Lithos

Dzięki @Wheat. Pytanie nie jest jasne, ale rozumiem teraz.
ElPedro

2
@KritixiLithos Aby zachować ciekawość, nie ma królowej ani pionka.
Wheat Wizard

Odpowiedzi:


8

Haskell , 447 439 437 432 bajtów

t=[1,2]
p=[(+),(-)]
f=filter
a=abs
(#)=elem
x?y=[min x y..max x y]
f&g=(\x->g x>>=f)
(b!1)(c,r)=f(#b)[(c!d,r#s)|(!)<-p,(#)<-p,d<-t,s<-t,d/=s]
(b!2)(c,r)=f(\(d,s)->(c==d&&all(#b)[(c,z)|z<-r?s])||r==s&&all(#b)[(z,r)|z<-c?d])b
(b!3)(c,r)=f(\(d,s)->a(c-d)==a(r-s)&&all(#b)(zip(c?d)$r?s))b
(b!4)(c,r)=f(\(d,s)->a(c-d)<2&&a(r-s)<2)b
(b%p)n s=[s]>>=foldr(&)(:[])(replicate n$b!p)
g b s e=head$f(not.null)[[p|p<-[1..4],e#(b%p)n s]|n<-[0..]]

Zadzwoń za pomocą g <board> <start> <end>gdzie <board> :: [(Int, Int)], <start> :: (Int, Int)i <end> :: (Int, Int). Zwraca listę zawierającą 1dla Rycerza, 2Wieży, 3Biskupa i 4Króla. Jeśli nie zostaną znalezione żadne rozwiązania, konsekwentnie przepełnia stos (co jest liczone jako zgłaszanie błędu, prawda?).

Inspiracja pochodzi z rozdziałów LYAH w sprawie Monads- (%)tylko uogólnione i grałem inManyz (&)odpowiednikiem (Control.Monad.<=<). Wszystko inne powinno być mniej lub bardziej oczywiste.

Prawdopodobnie można grać w golfa o wiele więcej, ale na razie miałem dość zabawy.

Nie golfowany:

data Piece = Knight | Rook | Bishop | King deriving (Show)
type Place = (Int, Int)
type Board = [Place]

x `to` y = [min x y..max x y]

f <=< g = (\x -> g x >>= f)

moves
    :: Board    -- available spaces
    -> Piece    -- type of piece
    -> Place    -- starting place
    -> [Place]  -- places available in one move
moves b Knight (c,r) =
    filter (`elem` b) [(c!d, r#s) |
                       (!) <- [(+),(-)], (#) <- [(+),(-)],
                       d <- [1,2], s <- [1,2], d/=s]
moves b Rook   (c,r) =
    filter (\(d,s) -> (c == d && all (`elem` b) [(c,z) | z <- r `to` s])
                    || r == s && all (`elem` b) [(z,r) | z <- c `to` d]) b
moves b Bishop (c,r) =
    filter (\(d,s) -> abs(c-d) == abs(r-s)
                && all (`elem` b) (zip (c `to` d) (r `to` s))) b
moves b King   (c,r) =
    filter (\(d,s) -> abs(c-d) <= 1 && abs(r-s) <= 1) b

canGoIn
    :: Board    -- available spaces
    -> Piece    -- type of piece
    -> Int      -- number of moves
    -> Place    -- starting place
    -> [Place]  -- places available in the specified number of moves
canGoIn b p n s =
    return s >>= foldr (<=<) return (replicate n (moves b p))

quickestPieces
    :: Board    -- available spaces
    -> Place    -- starting place
    -> Place    -- ending place
    -> [Piece]  -- quickest pieces
quickestPieces b s e =
        head $ filter (not.null)
            [[p | p <- [Knight, Rook, Bishop, King], elem e (canGoIn b p n s)] |
                n<-[0..]]

Ładne wykorzystanie programowania funkcjonalnego!
Wheat Wizard

5

Mathematica, 326 325 bajtów

Dzięki masterX224 za wskazanie oszczędności bajtów!

f[g_,w_,x_]:=(c={{1,1},{-1,1}};s=c.c/2;e=#<->#2&@@@#&;j=Join;h=FindShortestPath;t=#~Tuples~2&;a@d_:=e@Select[t@g,#-#2&@@#==d&];y@k=j@@(a/@j[s,c]);y@n=j@@(a/@{{1,2},{2,1},{-2,1},{-1,2}});v=Flatten[e@t@#&/@ConnectedComponents@a@#&/@#]&;y@r=v@s;y@b=v@c;Pick[p={b,k,n,r},z=Length[h[y@#,w,x]/.h@__->0]&/@p,Min[z~Complement~{0}]]);

Definiuje funkcję fprzyjmującą trzy argumenty: gjest listą uporządkowanych par liczb całkowitych reprezentujących tablicę woraz xuporządkowanych par reprezentujących kwadraty początkowy i końcowy. Wyjściem jest podzbiór {b, k, n, r}(reprezentujący odpowiednio biskupa, króla, rycerza i wieżę), które mają ścieżkę minimalnego ruchu między dwoma kwadratami. Na przykład trzeci przypadek testowy jest wywoływany przez f[{{0, 0}, {1, 1}, {1, 2}, {0, 3}}, {0, 0}, {0, 3}]i zwraca {k}; dwa ostatnie przypadki testowe wrócić {k, n}i {}odpowiednio.

Strategią jest przełożenie kwadratów planszy na wierzchołki wykresu, gdzie krawędzie są określane przez ruchy każdego elementu, a następnie użycie wbudowanych procedur graficznych.

Bardziej przyjazna dla użytkownika wersja kodu:

 1  f[g_, w_, x_] := ( c = {{1, 1}, {-1, 1}}; s = c.c/2;
 2    e = # <-> #2 & @@@ # &; j = Join; h = FindShortestPath; t = #~Tuples~2 &; 
 3    a@d_ := e@Select[t@g, # - #2 & @@ # == d &]; 
 4    y@k = j @@ (a /@ j[s, c]); 
 5    y@n = j @@ (a /@ {{1, 2}, {2, 1}, {-2, 1}, {-1, 2}}); 
 6    v = Flatten[e@t@# & /@
 7         ConnectedComponents@a@# & /@ #] &;
 8    y@r = v@s; y@b = v@c; 
 9    Pick[p = {b, k, n, r}, 
10      z = Length[h[y@#, w, x] /. h@__ -> 0] & /@ p, 
11      Min[z~Complement~{0}]]
12  );

W linii 3 Select[g~Tuples~2, # - #2 & @@ # == dznajduje wszystkie uporządkowane pary wierzchołków, których różnicą jest wektor d; enastępnie przekształca każdą taką uporządkowaną parę w niekierowaną krawędź wykresu. Tak więc ajest funkcja, która tworzy krawędzie między wszystkimi wierzchołkami, które różnią się stałym wektorem.

To wystarcza do zdefiniowania, w linii 4 i 5, wykres króla y@k(co ma związek krawędzi uzyskanych przez wektory {1, 1}, {-1, 1}, {0, 1}i {-1, 0}) oraz wykresu rycerskiej y@n(która ma to samo z {1, 2}, {2, 1}, {-2, 1}i {-1, 2}).

W linii 7 ConnectedComponents@a@#pobiera jeden z tych sąsiednich wykresów, a następnie wyszukuje połączone elementy; odpowiada to zgrupowaniu wszystkich segmentów linii wierzchołków w danym kierunku (tak, aby wieża lub biskup nie musieli się przez nie przemieszczać jeden po drugim). Następnie e@t@#w linii 6 umieszcza krawędzie między każdą parą wierzchołków w tym samym połączonym składniku, które są następnie Flattenedytowane w pojedynczy wykres. Zatem linie od 6 do 8 definiują wykres wieży i wykres y@rbiskupa y@b.

Wreszcie linie od 9 do 11 wybierają elementy, {b, k, n, r}które dają najkrótszą ścieżkę między dwoma docelowymi wierzchołkami. FindShortestPathwyrzuci błąd i zwróci nieoceniony, jeśli wierzchołek docelowy nie pojawi się na wykresie (co się stanie, jeśli z niego nie wyprowadzą się żadne krawędzie), więc zamiast tego używamy h@__ -> 0powrotu 0. Brak ścieżki między prawidłowymi wierzchołkami zwraca listę długości 0, więc Min[z~Complement~{0}]oblicza długość najmniejszej ścieżki, która faktycznie istnieje, ignorując powyższe niepoprawne przypadki.


jakiś powód podwójnego f w nazwie funkcji? czy jest to limit matematyczny?
masterX244,

och, haha, nie, to z mojej strony mentalny limit :) Miałem już fw tej sesji, ale powinienem to zmienić przed przesłaniem!
Greg Martin
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.