Thoát khỏi bàn cờ


23

Bạn thấy mình trên một bàn cờ, như người ta làm. Bạn có thể thấy lối ra nhưng nó ở rất xa và bạn thà không đi bộ hết đường. May mắn thay một số người dân địa phương đã cung cấp cho bạn một chuyến đi. Một Hiệp sĩ, một Rook, một Giám mục và một vị vua đều sẵn sàng đưa bạn đến đích của bạn, nhưng để xem đây là bàn cờ như thế nào thì mỗi người phải tuân thủ các quy tắc của cờ trên đường đến đích. Bạn muốn ra khỏi đây càng sớm càng tốt, bạn chấp nhận đề nghị của ai?

Bài tập

Cho một bàn cờ có hình dạng và kích thước tùy ý và hai điểm trên bàn cờ, xuất ra quân cờ có thể di chuyển giữa hai vị trí trong càng ít lần di chuyển càng tốt. Bảng sẽ không nhất thiết có nghĩa là liên tục có thể có khoảng cách giữa các phần của bảng. Mỗi trong số bốn quân cờ (Vua, Rook, Hiệp sĩ và Giám mục) có thể di chuyển theo các quy tắc tiêu chuẩn của họ trong cờ vua. Nữ hoàng và những người cầm đồ đã cố tình rời khỏi thử thách này.

Tôi / O

Bạn có thể nhận đầu vào ở bất kỳ định dạng hợp lý nào và bạn cũng có thể xuất ở bất kỳ định dạng nào bạn chọn. Đầu vào và đầu ra của bạn phải tự thống nhất. Nếu nhiều mảnh có thể đi đến đích trong cùng một số lần di chuyển, bạn phải xuất tất cả các mảnh có thể đến đó trong khoảng thời gian tối thiểu. Nếu không có phần nào trong bốn phần có thể đi đến cuối, bạn có thể xuất bất cứ thứ gì miễn là nó khác với tất cả các đầu ra có thể khác. Điều này có thể bao gồm đầu ra không có gì hoặc ném lỗi.

Các trường hợp thử nghiệm

Hình vuông biểu thị điểm bắt đầu và hình tròn biểu thị điểm kết thúc.


Kiểm tra 1

Giám mục


Kiểm tra 2

Hiệp sỹ


Bài kiểm tra 3

nhà vua


Kiểm tra 4

Tân binh


Kiểm tra 5

Vua, hiệp sĩ


Kiểm tra 6

không ai


Tốt đẹp. Tôi thích điều này nhưng không phải là một "bàn cờ có kích thước và hình dạng tùy ý" một thực thể duy nhất? Tôi thực sự không thấy các ví dụ 2 và 6 phù hợp với điều này như thế nào vì có vẻ như chúng là hai bảng riêng biệt mà chỉ hiệp sĩ mới có thể nhảy vào giữa. Có lẽ tôi đang thiếu một cái gì đó?
ElPedro

2
@ElPedro Họ vẫn là một bảng duy nhất, nó chỉ không phải là một bảng liên tục. Một phần của hình dạng tùy ý là các bảng có thể không liên tục.
Phù thủy lúa mì

Ví dụ 3, không nên là "vua, hoàng hậu"?
Kritixi Lithos

Cảm ơn @Wheat. Không chắc điều đó đã rõ ràng từ câu hỏi nhưng giờ tôi đã hiểu.
ElPedro

2
@KritixiLithos Để giữ cho mọi thứ thú vị, không có Nữ hoàng hay Cầm đồ.
Phù thủy lúa mì

Câu trả lời:


8

Haskell , 447 439 437 432 byte

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..]]

Gọi sử dụng g <board> <start> <end>ở đâu <board> :: [(Int, Int)], <start> :: (Int, Int)<end> :: (Int, Int). Trả về một danh sách chứa 1cho Knight, 2cho Rook, 3cho Giám mục và 4cho King. Nếu không có giải pháp nào được tìm thấy, nó sẽ liên tục tràn vào ngăn xếp (được tính là ném lỗi, phải không?).

Cảm hứng lấy từ các chương của LYAH trên Monads Sinh (%)chỉ là một khái quát và được đánh gôn inMany, (&)tương đương với (Control.Monad.<=<). Mọi thứ khác nên ít nhiều tự giải thích.

Điều này có thể có thể được chơi golf nhiều hơn nữa, nhưng bây giờ tôi đã có đủ niềm vui.

Ung dung:

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..]]

Sử dụng tốt các chương trình chức năng!
Phù thủy lúa mì

5

Toán học, 326 325 byte

Cảm ơn masterX224 đã chỉ ra một khoản tiết kiệm byte!

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}]]);

Xác định một hàm flấy ba đối số: glà danh sách các cặp số nguyên được sắp xếp đại diện cho bảng wxcác cặp được sắp xếp đại diện cho các ô vuông bắt đầu và kết thúc. Đầu ra là tập hợp con {b, k, n, r}(đại diện cho giám mục, vua, hiệp sĩ và tân binh), có đường di chuyển tối thiểu giữa hai hình vuông. Ví dụ, trường hợp thử nghiệm thứ ba được gọi bởi f[{{0, 0}, {1, 1}, {1, 2}, {0, 3}}, {0, 0}, {0, 3}]và trả về {k}; hai trường hợp thử nghiệm cuối cùng trở lại {k, n}{}, tương ứng.

Chiến lược là dịch các hình vuông của bảng thành các đỉnh của đồ thị, trong đó các cạnh được xác định bởi các bước di chuyển của từng mảnh, sau đó sử dụng các thói quen biểu đồ tích hợp.

Phiên bản mã thân thiện hơn với người dùng:

 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  );

Trong dòng 3, Select[g~Tuples~2, # - #2 & @@ # == dtìm tất cả các cặp đỉnh được sắp xếp có sự khác biệt là vectơ d; esau đó biến đổi từng cặp theo thứ tự như vậy thành một cạnh đồ thị vô hướng. Vậy alà một hàm tạo các cạnh giữa tất cả các đỉnh khác nhau bởi một vectơ cố định.

Đó là đủ để xác định, trong dòng 4 và 5, đồ thị của nhà vua y@k(mất công đoàn của các cạnh được tạo ra bởi các vectơ {1, 1}, {-1, 1}, {0, 1}, và {-1, 0}) và đồ thị của hiệp sĩ y@n(mà cũng làm như vậy với {1, 2}, {2, 1}, {-2, 1}, và {-1, 2}).

Trong dòng 7, ConnectedComponents@a@#lấy một trong các biểu đồ lân cận này và sau đó tìm các thành phần được kết nối của nó; điều này tương ứng với việc nhóm tất cả các phân đoạn của các đỉnh theo hướng đã cho (để một tân binh hoặc giám mục không phải di chuyển qua từng điểm một). Sau đó, e@t@#trên dòng 6 đặt các cạnh giữa mỗi cặp đỉnh trong cùng một thành phần được kết nối, sau đó được Flattened thành một biểu đồ duy nhất. Do đó, các dòng 6 đến 8 xác định biểu đồ của tân y@rbinh và biểu đồ của giám mục y@b.

Cuối cùng, các dòng 9 đến 11 chọn các phần tử {b, k, n, r}tạo ra đường đi ngắn nhất giữa hai đỉnh đích. FindShortestPathsẽ đưa ra một lỗi và trả về không đánh giá được nếu một đỉnh đích không xuất hiện trong biểu đồ (điều này sẽ xảy ra nếu không có cạnh nào phát ra từ nó), vì vậy chúng tôi sử dụng h@__ -> 0để trả về 0trong các trường hợp đó. Và việc thiếu một đường dẫn giữa các đỉnh hợp lệ sẽ trả về một danh sách độ dài 0, vì vậy hãy Min[z~Complement~{0}]tính độ dài của đường dẫn nhỏ nhất thực sự tồn tại, bỏ qua các trường hợp xấu ở trên.


bất kỳ lý do cho đôi f trong tên hàm? hoặc nó là một giới hạn toán học?
masterX244 17/03/17

oh, haha, không có giới hạn về mặt tinh thần đối với tôi :) Tôi đã có một fphiên trong đó rồi, nhưng tôi nên thay đổi nó trước khi nộp!
Greg Martin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.