체스 판을 탈출


23

체스 판에서 자신을 찾을 수 있습니다. 출구를 볼 수는 있지만 출구가 너무 먼 거리에 있습니다. 운 좋게도 일부 지역 주민들은 당신에게 타고를 제공했습니다. 기사, 루크, 주교, 왕은 모두 당신을 당신의 목적지로 데려다 줄 것입니다. 그러나 이것이 체스 판인지 어떻게되는지 그들은 그들이 목적지로가는 길에 체스 규칙을 따라야합니다. 가능한 한 빨리 여기서 나가고 싶습니다. 누구의 제안을 수락 하시겠습니까?

태스크

임의로 모양과 크기의 체스 판과 체스 판의 두 점이 주어지면 가능한 한 적은 움직임으로 두 위치 사이를 이동할 수있는 체스 조각을 출력합니다. 보드는 반드시 연속적인 의미 일 필요는 없으며 보드의 섹션 사이에 간격이있을 수 있습니다. 4 가지 작품 (킹, 루크, 나이트, 비숍)은 체스의 표준 규칙에 따라 움직일 수 있습니다. 여왕과 전당포 조각은 의도적으로이 도전에서 제외되었습니다.

I / O

합리적인 형식으로 입력 할 수 있으며 원하는 형식으로도 출력 할 수 있습니다. 입력과 출력은 일관되어야합니다. 여러 조각이 같은 수의 이동으로 대상에 도달 할 수있는 경우 최소 시간 내에 도달 할 수있는 모든 조각을 출력해야합니다. 4 개 중 어느 것도 끝까지 만들 수 없다면 다른 모든 가능한 출력과 구별되는 한 아무것도 출력 할 수 있습니다. 아무것도 출력하지 않거나 오류가 발생할 수 있습니다.

테스트 사례

사각형은 시작점을 나타내고 원은 끝점을 나타냅니다.


시험 1

주교


시험 2

기사


시험 3


시험 4

사기꾼


시험 5

왕, 기사


시험 6

없음


좋은. 나는 이것을 좋아하지만 "임의의 모양과 크기의 체스 판"은 하나의 실체가 아닌가? 예제 2와 6은 기사만이 이동할 수있는 두 개의 별도 보드 인 것처럼 보이기 때문에 실제로 어떻게 적용되는지 알지 못합니다. 어쩌면 내가 뭔가를 놓치고 있습니까?
ElPedro

2
@ElPedro 그들은 여전히 ​​하나의 보드이며, 단지 연속적인 보드가 아닙니다. 임의의 모양의 일부는 보드가 비 연속적 일 수 있다는 것입니다.
위트 마법사

예를 들어 3, "왕, 여왕"이 아니어야합니까?
Kritixi Lithos

감사합니다 @ 밀. 그 질문에서 분명하지는 않지만 지금 이해합니다.
ElPedro

2
@KritixiLithos 흥미로운 것들을 유지하기 위해 Queen이나 Pawn은 없습니다.
밀 마법사

답변:


8

하스켈 , 447 439 437 432 바이트

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 <board> <start> <end><board> :: [(Int, Int)], <start> :: (Int, Int)하고 <end> :: (Int, Int). 1기사, 2루크, 3비숍 및 4킹을 포함하는 목록을 반환합니다 . 해결책을 찾지 못하면 지속적으로 스택을 오버플로합니다 (오류가 발생하는 것으로 간주됩니다).

Monads-에 LYAH의 장에서 가져온 영감은 (%)단지 일반화 golfed입니다 inMany함께 (&)동등 (Control.Monad.<=<). 다른 모든 것들은 다소 설명이 필요합니다.

이것은 아마도 더 많은 골프를 쳤을 수도 있지만, 지금은 충분히 재미있었습니다.

언 골프 드 :

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

함수형 프로그래밍의 좋은 사용!
위트 마법사

5

매스 매 티카, 326325 바이트

바이트 절약을 알려 주신 masterX224에 감사드립니다!

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

함수 정의 f세 개의 인수를 복용은 : g보드를 나타내는 정수의 순서쌍의 목록이며, w그리고 x시작과 끝 사각형을 나타내는 쌍을 주문했다. 출력은 {b, k, n, r}두 개의 사각형 사이에 최소 이동 경로가있는 (주교, 왕, 기사 및 루크를 나타내는) 하위 집합입니다 . 예를 들어, 세 번째 테스트 케이스에 의해 호출 f[{{0, 0}, {1, 1}, {1, 2}, {0, 3}}, {0, 0}, {0, 3}]반환 {k}; 마지막 두 테스트 케이스는 반환 {k, n}{}각각.

전략은 보드의 정사각형을 그래프의 정점으로 변환하는 것입니다.이 정점은 각 조각의 움직임에 따라 가장자리가 결정되며 내장 된 그래프 루틴을 사용합니다.

보다 사용자 친화적 인 코드 버전 :

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

3 행에서 Select[g~Tuples~2, # - #2 & @@ # == d차이가 벡터 인 모든 정점 쌍을 찾습니다 d. e그런 다음 순서가 지정된 각 쌍을 방향이 지정되지 않은 그래프 가장자리로 변환합니다. 따라서 a, 고정 벡터 차이 모든 꼭지점 사이의 에지를 생성하는 함수이다.

4, 5 행에서 왕의 그래프를 정의하기에 충분합니다. y@k (벡터에 의해 생성 된 가장자리의 결합을 얻어 {1, 1}, {-1, 1}, {0, 1}, 및 {-1, 0}) 및 나이트의 그래프 y@n(와 동일한 않는 {1, 2}, {2, 1}, {-2, 1}, 및 {-1, 2}).

7 행 ConnectedComponents@a@#에서이 인접 그래프 중 하나를 가져온 다음 연결된 구성 요소를 찾습니다. 이것은 정점의 모든 선분을 주어진 방향으로 그룹화하는 것에 해당합니다 (루크 나 감독이 하나씩 통과 할 필요가 없습니다). 그런 다음 e@t@#6 행에서 동일한 연결된 구성 요소의 모든 정점 쌍 사이에 모서리를두고 Flatten단일 그래프로 연결합니다. 따라서 6-8 행은 루크의 그래프 y@r와 감독의 그래프를 정의합니다 y@b.

마지막으로 9 ~ 11 행 {b, k, n, r}은 두 대상 정점 사이의 최단 경로를 생성하는 요소를 선택합니다 . FindShortestPath우리가 사용하는, 그래서 오류가 발생하고 대상 정점 (더 가장자리 그것에서 발산하지 않는 경우 일 것이다) 그래프에 표시되지 않을 경우 평가되지 않은 반환 h@__ -> 0으로 돌아 가기0 대신 . 유효한 정점 사이의 경로가 없으면 length 목록을 반환 0하므로 Min[z~Complement~{0}]실제로 존재하는 가장 작은 경로의 길이를 계산하여 위의 나쁜 경우를 무시하십시오.


함수 이름에 이중 f가있는 이유는 무엇입니까? 아니면 수학적인 한계입니까?
masterX244

오, 하하, 아니 그것은 내 부분에 정신적 한계가 있습니다 :) 나는 f이미 그 세션에 있었지만 제출하기 전에 그것을 바꿔야했습니다!
Greg Martin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.