장군인가요?


14

Wholly는 사이트에 많은 수의 체스 퍼즐이 있기 때문에 아직 게시되지 않은 것에 놀랐습니다. 나는 이것을 스스로 생각했지만 3 월에 샌드 박스게시 한 Anush에게 감사의 뜻을 전한다 . 그러나 나는 나 자신이 그렇게 할 수있을만큼 오래 걸렸다 고 생각했다.

체스 의 수표 는 왕이 공격을 당하고 그것을 방어 할 수있는 움직임이없는 위치입니다. 체스 조각의 움직임에 익숙하지 않다면 Wikipedia에 익숙해 질 수 있습니다 .

도전

이 도전을 위해, 당신의 입력은 당신이 원하는 표기법으로 체스 판의 위치가 될 것입니다. 명확히하기 위해, 귀하의 의견은 수와 함께 자신의 색상과 위치와 함께, 체스 보드에 조각을 설명 할 것이다 ...하는 김에 있는 경우, 캡처 광장. (성을 확인할 수 없으므로 성 기능은 관련이 없습니다.) FEN 표기법이 유용 할 수 있지만 편리한 형식은 괜찮습니다. 간단하게하기 위해 블랙을 플레이한다고 가정 할 수 있습니다. 즉, 블랙은 항상 체크 된 플레이어입니다. White가 체크, 체크 메이트 또는 교착 상태에있는 위치는이 챌린지에 유효하지 않은 것으로 간주됩니다.

위치가 checkmate 인 경우 정확한 값을, 그렇지 않은 경우 잘못된 값을 출력해야합니다. 참고 교착 상태가 장군되지 왕이 공격을해야합니다 -!

확실한 테스트 사례

1k5R / 6R1 / 8 / 8 / 8 / 8 / 8 / 6K1 b--

rn2r1k1 / pp1p1pQp / 3p4 / 1b1n4 / 1P2P3 / 2B5 / P5PP / R3K2R b--

kr5R / rB6 / 8 / 8 / 8 / 5Q2 / 6K1 / R7 b--

2K5 / 1B6 / 8 / 8 / 8 / 7N / R7 / R3r2k b--0 1

8 / 4Q1R1 / R7 / 5k2 / 3pP3 / 5K2 / 8 / 8 b--

2K5 / 1B6 / 8 / 8 / 8 / 4b2N / R7 / 4r2k b--

팔시 테스트 사례

rnbqkbnr / pppppppp / 8 / 8 / 4P3 / 8 / PPPP1PPP / RNBQKBNR b KQkq-

8 / 8 / 8 / 8 / 8 / 1KQ5 / 4N3 / 1k6 b--

2K5 / 1B6 / 8 / 8 / 8 / 7N / R7 / 4r2k b--

8 / 8 / 2Q5 / 3k4 / 3Q5 / 8 / 8 / 7K b--

8 / 4Q1R1 / R7 / 5k2 / 3pP3 / 5K2 / 8 / 8 b-e3 ( 동시 시청)

코드 골프-바이트 단위의 가장 짧은 코드가 이깁니다. 행운을 빕니다!


2
이것은 좋은 질문처럼 보입니다 :)
Anush

1
여기에 모든 도전이 있어야 할 자급 자족을 위해 외부 링크에 의존하거나 체스의 규칙과 표기법에 대한 기존의 지식을 가정하는 것보다 훨씬 더 많은 노력을 기울여야합니다. 작업하는 동안 샌드 박스로 가져가는 것이 좋습니다.
Shaggy

3
@Shaggy이 챌린지의 외부 링크는 편의상 제공됩니다. 대부분의 다른 체스 과제는 사전 지식이 있다고 가정하기 때문에 체스의 모든 규칙을 여기에 나열하지는 않겠습니다. 그리고 lichess 링크는 테스트 사례를 시각적으로 쉽게 보여줍니다. 이 표기법은 리치 외부에서 잘 정의되어 있습니다. 나는 이미지를 추가 할 수는 있지만 많은 혼란처럼 느껴지지 않기로 결정했습니다.
산란

1
보드가 유효한 게임을 통해 도착했다고 가정 할 수 있습니까?
애드혹 가프 헌터

1
핵심 과제는 동일하지만이 과제는 훨씬 더 느슨하고 (정직하게는 더 나은) IO 체계와 약간 다른 (정직하게는 더 나은) 점수 기준을 갖기 때문에 이것을 다시 열었습니다. 나는 아마도 오래된 것이 새로운 것의 속임수로 폐쇄되어야한다고 생각하지만 그것을 망치지 않을 것입니다.
Ad Hoc Garf Hunter

답변:


10

자바 스크립트 (Node.js) ,  499 ... 374370  바이트

입력을로 취합니다 (b)(X). 여기서 는 제곱을 설명하는 64 개의 정수 배열 (왼쪽에서 오른쪽으로, 위에서 아래로)이며 는 동반 대상 사각형의 0 기반 인덱스이거나 없는 경우 입니다.bX1

다음은 각 사각형의 예상 값입니다.

 0: empty square

 5: white pawn      6: black pawn
 9: white king     10: black king
17: white bishop   18: black bishop
33: white rook     34: black rook
49: white queen    50: black queen
65: white knight   66: black knight

checkmate의 경우 를, not-checkmate의 경우 을 반환 합니다.640

b=>e=>(g=(c,k)=>b.map((v,p,h,s=p+(p&~7),M=t=>v&-~c?c?(B=[...b],K&=g(b[t?b[T]=b[p]:b[b[e-8]=0,e]=6,p]=0),b=B):k|=V&8:0,m=([a],[x,t,...d]=Buffer(a))=>d.map(c=>(h=n=>(V=(a+=c-66)&136?3:b[T=a+a%8>>1])&v&3||t>>!V&v>>x&n>31&&h(n-4/!V,M``))(t,a=s)))=>(v=b[p],m`##123ACQRS`,m`$?13QS`,m`%?2ACR`,m`&#!#04PTac`,c?(p-e+8.5&~1||M(),m`"!QS`,p<16?m`"&R`:m`""R`):m`"!13`))|k)(1,K=g())*K

온라인으로 사용해보십시오!

어떻게?

보드 표현

우리는 고전적인 0x88 보드 표현을 사용하여 범위를 벗어난 대상 사각형을 쉽게 감지 할 수 있습니다.

   |  a    b    c    d    e    f    g    h
---+----------------------------------------
 8 | 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 
 7 | 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 
 6 | 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 
 5 | 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 
 4 | 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 
 3 | 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 
 2 | 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 
 1 | 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77

인코딩 이동

각 동작 세트는 5 개의 매개 변수로 인코딩됩니다.

  • 조각의 유형
  • 각 방향으로 방문 할 수있는 최대 제곱 수
  • 캡처가 허용되는지를 나타내는 플래그
  • 비 캡쳐가 허용되는지를 나타내는 플래그
  • 길 찾기 목록

이러한 모든 매개 변수는 단일 문자열로 묶여 있습니다. 예를 들어 기사 이동은 다음과 같이 인코딩됩니다.

`&#!#04PTac`
 ||\______/
 ||    |                            +------> 0 + 1 = 1 square in each direction
 ||    |                            | +----> standard moves allowed
 ||    +---> 8 directions           | |+---> captures allowed
 ||                                / \||
 |+--------> ASCII code = 35 = 0b0100011
 |
 +---------> 1 << (ASCII code MOD 32) = 1 << 6 = 64

방향을 해독하기 위해 ASCII 코드에서 을 뺍니다 .66

 char. | ASCII code | -66
-------+------------+-----
  '!'  |     33     | -33
  '#'  |     35     | -31
  '0'  |     48     | -18
  '4'  |     52     | -14
  'P'  |     80     | +14
  'T'  |     84     | +18
  'a'  |     97     | +31
  'c'  |     99     | +33

이것은 다음을 제공합니다.

 [ - ] [-33] [ - ] [-31] [ - ]
 [-18] [ - ] [ - ] [ - ] [-14]
 [ - ] [ - ] [ N ] [ - ] [ - ]
 [+14] [ - ] [ - ] [ - ] [+18]
 [ - ] [+31] [ - ] [+33] [ - ]

개별적으로 처리되는 수동 캡처를 제외하고 모든 이동 세트가 다음 표에 요약되어 있습니다.

  string    | description             | N | S | C | directions
------------+-------------------------+---+---+---+----------------------------------------
 &#!#04PTac | knight                  | 1 | Y | Y | -33, -31, -18, -14, +14, +18, +31, +33
 ##123ACQRS | king                    | 1 | Y | Y | -17, -16, -15, -1, +1, +15, +16, +17
 "!13       | white pawn / captures   | 1 | N | Y | -17, -15
 "!QS       | black pawn / captures   | 1 | N | Y | +15, +17
 "&R        | black pawn / advance x2 | 2 | Y | N | +16
 ""R        | black pawn / advance x1 | 1 | Y | N | +16
 $?13QS     | bishop or queen         | 8 | Y | Y | -17, -15, +15, +17
 %?2ACR     | rook or queen           | 8 | Y | Y | -16, -1, +1, +16

댓글

b => e => (
  // generate all moves for a given side
  g = (c, k) =>
    b.map((
      v, p, h,
      // s = square index in 0x88 format
      s = p + (p & ~7),
      // process a move
      M = t =>
        // make sure that the current piece is of the expected color
        v & -~c ?
          c ?
            // Black's turn: play the move
            ( // board backup
              B = [...b],
              // generate all White moves ...
              K &= g(
                // ... after the board has been updated
                b[
                  t ?
                    // standard move
                    b[T] = b[p]
                  :
                    // en-passant capture
                    b[b[e - 8] = 0, e] = 6,
                  p
                ] = 0
              ),
              // restore the board
              b = B
            )
          :
            // White's turn: just update the king's capture flag
            k |= V & 8
        :
          0,
      // generate all moves of a given type for a given piece
      m = ([a], [x, t, ...d] = Buffer(a)) =>
        d.map(c =>
          ( h = n =>
            ( // advance to the next target square
              V = (a += c - 66) & 136 ? 3 : b[T = a + a % 8 >> 1]
            )
            // abort if it's a border or a friendly piece
            & v & 3 ||
            // otherwise: if this kind of move is allowed
            t >> !V &
            // and the current piece is of the expected type
            v >> x &
            // and we haven't reached the maximum number of squares,
            n > 31 &&
            // process this move (if it's a capture, force n to
            // -Infinity so that the recursion stops)
            h(n - 4 / !V, M``)
          )(t, a = s)
        )
    ) =>
      (
        v = b[p],
        // king
        m`##123ACQRS`,
        // bishop or queen
        m`$?13QS`,
        // rook or queen
        m`%?2ACR`,
        // knight
        m`&#!#04PTac`,
        c ?
          // black pawn
          ( // en-passant capture
            p - e + 8.5 & ~1 || M(),
            // standard captures
            m`"!QS`,
            // standard moves
            p < 16 ? m`"&R` : m`""R`
          )
        :
          // white pawn (standard captures only)
          m`"!13`
      )
    ) | k
// is the black king in check if the Black don't move?
// is it still in check after each possible move?
)(1, K = g()) * K

8/1ppp4/1pkp4/8/2Q5/8/8/7K b - -
tsh

@tsh 훨씬 더 심각한 버그. 현재 6 바이트의 비용으로 수정되었습니다.
Arnauld

동반자가 가능한지 여부를 알려주는 표현이 없으면 어떻게 작동합니까?
Anush

@Anush 매개 변수는이 정보를 보유합니다. X
Arnauld '

아하. 매우 감사합니다.
Anush

6

하스켈 , 1165 1065 1053 바이트

Leo Tenenbaum 덕분에 바이트 절약

n=Nothing
x?y=Just(x,y)
o(x,y)=x<0||y<0||x>7||y>7
m#k@(x,y)|o k=n|1>0=m!!x!!y
z(x,y)m p(a,b)|o(x+a,y+b)=1<0|Just g<-m#(x+a,y+b)=elem g[(p,0),(5,0)]|1>0=z(x+a,y+b)m p(a,b)
t(x,y)p(a,b)m|o(x+a,y+b)=[]|g<-(x+a,y+b)=(g%p)m++do[0|m#g==n];t g p(a,b)m
c m|(x,y):_<-[(a,b)|a<-u,b<-u,m#(a,b)==6?1],k<-z(x,y)m=or$[m#(x+a,y+b)==6?0|a<-0:s,b<-0:s]++do a<-s;[k 3(a,b)|b<-s]++(k 2<$>[(a,0),(0,a)])++[m#l==4?0|b<-[2,-2],l<-[(x+a,y+b),(x+b,y+a)]]++[m#(x-1,y+a)==p?0|p<-[0,1]]
c m=1>0
(k%p)m=[[[([p|a==k]++[m#a])!!0|a<-(,)b<$>u]|b<-u]|not$o k]
w(Just(_,1))=1<0
w x=1>0
m!u@(x,y)|g<-m#u,Just(q,1)<-g,v<-((u%n)m>>=),r<-v.t u g,k<-(do[0|n==m#(x+1,y)];(u%n)m>>=(x+1,y)%g)++(do a<-s;[0|n<m#(x+1,y+a)];v$(x+1,y+a)%g)++(do[0|(x,n,n)==(1,m#(x+1,y),m#(x+2,y))];v$(x+2,y)%g)++(do a<-s;[0|1?0==m#(x,y+a)];v((x,y+a)%n)>>=(x+1,y+a)%g)=[k,k,do a<-s;[(a,0),(0,a)]>>=r,do a<-s;b<-s;r(a,b),do a<-s;b<-[2,-2];l<-[(x+a,y+b),(x+b,y+a)];v$l%g,do a<-0:s;b<-[0|a/=0]++s;r(a,b),do a<-[x-1..x+1];b<-[y-1..y+1];[0|w$m#(a,b)];v$(a,b)%g]!!q
m!u=[]
u=[0..7]
s=[1,-1]
q m=all c$m:do a<-u;b<-u;m!(a,b)

온라인으로 사용해보십시오!

이것은 현재 정확히 골프는 아니지만 시작입니다. 내가 지금 방법을 따라 약간의 도움으로 골프를 꽤 공격적으로 (그리고 도중에 오류를 수정).

이것이 의심스러운 일 중 하나는 왕이나 전당포가 아닌 다른 사람이 자신의 작품 중 하나를 캡처하여 확인할 수 없다는 가정입니다. 체스에서는이 이동을 허용하지 않지만 내 프로그램은 바이트를 절약하기 위해 이러한 이동을 고려하여 체크 인하면 결코 벗어날 수 없다는 가정하에 바이트를 절약합니다.

이러한 가정은 그러한 움직임 때문에 유효합니다

  1. 왕을 공격하는 조각은 검은 색이기 때문에 캡처 할 수 없습니다.

  2. 캡처 된 검은 조각이 이미 그렇게했기 때문에 왕을 공격하는 조각의 경로를 차단할 수 없습니다.

우리는 또한 왕이 없다면 당신이 확인하고 있다는 추가 규정을 추가합니다.

이 프로그램은 또한 막을 수있는 폰이 있다면 폰은 마지막으로 움직였으며 그 움직임은 합법적 인 움직임이라고 가정합니다. 프로그램이 검은 폰을 움직이는 사각형이 비어 있는지 확인하지 않기 때문에 조각이 있으면 약간 나사가 생길 수 있습니다. 그러나 마지막 이동이 합법적 이동이며 FEN 으로 표시 될 수없는 경우에는이를 얻을 수 없습니다 . 따라서이 가정은 다소 견고합니다.

다음은 참고 용으로 "ungolfed"버전입니다.

import Control.Monad
out(x,y)=x<0||y<0||x>7||y>7
at b (x,y)
  |out(x,y)=Nothing
  |otherwise=(b!!x)!!y
inLine (x,y) ps m (a,b) 
  | out (x+a,y+b) = False
  | elem (m `at` (x+a,y+b)) $ Just <$> ps = True
  | m `at` (x+a,y+b) == Nothing = inLine (x+a,y+b) ps m (a,b) 
  | otherwise = False
goLine (x,y) p (a,b)m
  | out (x+a,y+b) = []
  | otherwise = case m `at` (x+a,y+b) of
--    Just (n,1) -> []
    Just (n,_) -> set(x+a,y+b)p m
    Nothing    -> set(x+a,y+b)p m ++ goLine(x+a,y+b)p(a,b)m
checkBishop (x,y) m=or[inLine(x,y)[(3,0),(5,0)]m(a,b)|a<-[1,-1],b<-[1,-1]]
checkRook   (x,y) m=or$do
  a<-[1,-1]
  inLine(x,y)[(2,0),(5,0)]m<$>[(a,0),(0,a)]
checkKnight (x,y) m=any((==Just(4,0)).(at m))$do
  a<-[1,-1]
  b<-[2,-2]
  [(x+a,y+b),(x+b,y+a)]
checkPawn (x,y) m=or[at m a==Just(p,0)|a<-[(x-1,y+1),(x-1,y-1)],p<-[0,1]]
checkKing (x,y) m=or[at m(a,b)==Just(6,0)|a<-[x-1..x+1],b<-[y-1..y+1]]
check m
  | u:_<-[(a,b)|a<-[0..7],b<-[0..7],(m!!a)!!b==Just(6,1)] =
    checkBishop u m ||
    checkRook   u m ||
    checkKnight u m ||
    checkPawn   u m ||
    checkKing   u m
  | otherwise = True
set (x,y) p m=[[[head$[p|(a,b)==(y,x)]++[(m!!b)!!a]|a<-[0..7]]|b<-[0..7]]|not$out(x,y)]
white(Just(n,0))=True
white x=False
moves m (x,y)
 |g<-m `at` (x,y)=case g of
  Just(2,1) -> do
    a<-[1,-1]
    b<-[(a,0),(0,a)]
    set(x,y)Nothing m>>=goLine (x,y) g b
  Just(3,1) -> do
    a<-[1,-1]
    b<-[1,-1]
    set(x,y)Nothing m>>=goLine (x,y) g(a,b)
  Just(4,1) -> do
    n<-set(x,y)Nothing m
    a<-[1,-1]
    b<-[2,-2]
    l<-[(x+a,y+b),(x+b,y+a)]
    -- guard$white$n `at` l
    set l g n
  Just(5,1) -> do
    a<-[1,-1]
    c<-[(a,0),(0,a),(a,1),(a,-1)]
    set(x,y)Nothing m>>=goLine (x,y) g c
  Just(6,1) -> do
    a<-[x-1..y+1]
    b<-[x-1..y+1]
    guard$white(m `at`(a,b))||Nothing==m`at`(a,b)
    set(x,y)Nothing m>>=set(a,b)g
  Just(n,1) -> (do
    guard$Nothing==m `at` (x+1,y)
    set(x,y)Nothing m>>=set(x+1,y)g) ++ (do
      a<-[1,-1]
      guard$white$m`at`(x+1,y+a)
      set(x,y)Nothing m>>=set(x+1,y+a)g) ++ (do
        guard$(x,Nothing,Nothing)==(1,m`at`(x+1,y),m`at`(x+1,y))
        set(x,y)Nothing m>>=set(x+2,y)g) ++ (do
          a<-[1,-1]
          guard$Just(1,0)==m`at`(x,y+a)
          set(x,y)Nothing m>>=set(x,y+a)Nothing>>=set(x+1,y+a)g)
  _ -> []
checkmate m=all check$m:do
  a<-[0..7]
  b<-[0..7]
  moves m(a,b)

온라인으로 사용해보십시오!


약간의 골프와 함께 1252 바이트 (TIO 링크가 너무
Leo Tenenbaum

@LeoTenenbaum 감사합니다. 불행히도이 문제를 곧 통합 할 예정입니다. 현재 수정 한 버전에 실수로 두 가지 실수가있었습니다. 이 긴 프로그램을 통해 많은 방법으로 개선 할 여지가 분명히 있습니다.
Ad Hoc Garf Hunter

@ tsh yep, 나는 킹스 위치를 가고있는 곳에 추가하는 것을 잊었다. 수정 됨
Ad Hoc Garf Hunter 13:27의

목록의 경우 몇 바이트를 더 절약 guard x = [0|x]할 수 있습니다 x?y=Just(x,y). 1129 바이트
Leo Tenenbaum

1

Python 3 (PyPy) , 729 바이트

F=lambda a,b:a<'^'<=b or a>'^'>=b
def m(b,P,A=0):
 yield b
 for(r,f),p in b.items(): 
  if F(P,p):continue
  *d,n,k={'R':[(0,1),8,4],'N':[(1,2),(2,1),2,4],'B':[(1,1),8,4],'Q':[(0,1),(1,1),8,4],'K':[(0,1),(1,1),2,4],'P':[(2,0),(1,0),(1,1),(1,-1),2,1],'p':[(-2,0),(-1,0),(-1,1),(-1,-1),2,1]}[p if p=='p'else p.upper()]
  if p in'pP':d=d[d!=[2,7][p=='p']+A:]
  for u,v in d:
   for j in range(k):
    for i in range(1,n):
     U=r+u*i;V=f+v*i;t=b.get((U,V),'^')
     if U<1or U>8or V<1 or V>8:break
     if F(p,t):
      B=dict(b);B[(U,V)]=B.pop((r,f))
      if t in'eE':B.pop(([U+1,U-1][t=='e'],V))
      yield B
     if t not in'^eE':break
    u,v=v,-u
M=lambda b:all(any('k'not in C.values()for C in m(B,'W',1))for B in m(b,'b'))

온라인으로 사용해보십시오!


이것은 현재 검사에 실패합니다 8/2p5/Q7/Q2k4/Q7/8/8/7K b - -.
Arnauld
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.