이 문자열이 유효한가요?


12

도전

문자열 입력을 함수 매개 변수 또는 stdin에서 가져 와서 유효한 FEN 문자열 인지 판별하는 프로그램 또는 함수를 작성하십시오 .

입력

입력은 다음 문자 만 포함한다고 가정 할 수 있습니다 (대소 문자 구분)
pkqrbnPKQRBN12345678/
입력 길이는 항상 최소 1 자에서 최대 100 자입니다.

산출

결과는 진실 / 거짓 값이어야합니다. 일관된 한 원하는 값이 될 수 있습니다 (모든 진실 된 결과는 동일한 결과를 가지며 모든 거짓된 결과는 동일한 결과를 갖습니다). 정확히 두 가지 가능한 출력이 있어야합니다.

유효한 것으로 간주되는 것

소문자는 검은 색 조각을 나타내고 대문자는 흰색 조각을 나타냅니다.
체스 게임에서 현재 위치의 조각이 존재할 수 있는지 확인해야합니다.
각 플레이어는 항상 정확히 1 킹 (k / K)을
갖습니다. 각 플레이어는 폰 (p / P)을
넘지 않아야합니다. 각 플레이어는 보통 1 * 퀸 (q / Q)을 넘지
않습니다. 2 * 루크 (r / R) 이상
각 플레이어는 보통 2 * 기사 (n / N)를
넘지 않습니다. 각 플레이어는 일반적으로 2 * 주교 (b / B)를 넘지 않습니다
* 플레이어는 ' 이 네 조각 중 하나에 폰을 홍보하십시오.
각 플레이어의 폰, 퀸, 루크, 나이트 및 주교의 총 수는 15를 넘지 않습니다.

총 조각 수와 빈 사각형 (숫자로 표시)은 항상 각 등급에 대해 정확히 8을 더해야합니다. 그리고 슬래시로 구분하여 항상 정확히 8 개의 순위가 있어야합니다.

무시할 수있는 것

표시된 포지션으로 플레이 할 수 있는지 또는 포지션이 합법적이라면 주어진 수량으로 조각 만 존재할 수 있는지에 대해 걱정할 필요가 없습니다.
플레이어 턴, 캐스터 링 권한 및 동반자와 같은 FEN 문자열의 추가 복잡성을 무시할 수 있습니다.

이것은 코드 골프입니다. 바이트 단위의 최단 프로그램이 이깁니다. 일반적인 허점과 규칙이 적용됩니다.

테스트 사례

입력 rnbqkbnr / pppppppp / 8 / 8 / 8 / 8 / PPPPPPPP / RNBQKBNR
출력 True

입력 2br2k1 / 1p2n1q1 / p2p2p1 / P1bP1pNp / 1BP2PnP / 1Q1B2P1 / 8 / 3NR2K
출력 True

입력 r2r2k1 / p3q2p / ppR3pr / rP4bp / 3p4 / 5B1P / P4PP1 / 3Q1RK1
출력 False
(검정색은 7 폰 및 4 루크-불가능)

입력 6k1 / pp3ppp / 4p3 / 2P3b1 / bPP3P1 / 3K4 / P3Q1q1
출력 거짓 (7 순위 만)

입력 3r1rk1 / 1pp1bpp1 / 6p1 / pP1npqPn / 8 / 4N2P / P2PP3 / 1B2BP2 / R2QK2R
출력 거짓 (9 랭크)

입력 5n1k / 1p3r1qp / p3p3 / 2p1N2Q / 2P1R3 / 2P5 / P2r1PP1 / 4R1K1
출력 False (2 순위는 9 제곱 / 조각)

입력 rnbqkbnr / pppppppp / 35분의 8 / 8 / 8 / PPPPPPPP / RNBQKBNR의
출력이
이 경우를위한 명확하고 Feersum Arnauld 감사 (3 + 5 = 8)

펜이란?

FEN 은 체스 판에 조각의 위치를 ​​기록하기위한 표준 표기법입니다. 이미지 크레디트 http://www.chessgames.com여기에 이미지 설명을 입력하십시오


“각 플레이어는 보통 1 * 여왕을 넘지 않습니다.”“정상”으로 간주되는 것이 중요하지 않기 때문에 유효한 것으로 간주되는 것을 명확히하십시오. 백인이 9 명의 여왕을 갖는 것이 유효합니까? 여왕 10 명? 전당포 8 명과 여왕 2 명? 제로 킹스? 첫 번째 또는 마지막 순위에서 프로모션되지 않은 폰?
Anders Kaseorg

@AndersKaseorg * It is legal for a player to 'promote' a pawn to any of these four pieces.폰의 수를 줄여 보상하는 한, 플레이어는 최대 9 명의 여왕을 가질 수 있습니다. 조각의 위치가 합법적이거나 불법적 인 것에 대해 걱정할 필요는 없으며 조각 수만 있습니다.
Darren H

1
세 번째 테스트 사례에서 검정은 7
개가

1
@DarrenH feersum에서 제안한 FEN 위치는 현재 규칙에 따라 유효합니다. 358 개의 빈 사각형을 설명하는 특별한 방법입니다.
Arnauld

1
첫 번째 또는 마지막 순위에 @PatrickRoberts 졸 있는 이 도전의 목적을 위해 유효한. 위치의 적법성을 설명 할 필요는 없으며 조각의 수량 만 고려하십시오. 포지션의 합법성에 대한 설명 (예 : 두 선수 모두 점검 중)은 복잡성을 심화시킵니다. 따라서 '포지션이 중요하지 않습니다'라는 담요가 어디에서 설명 해야하는지에 대한 토론을하는 것보다 명확하다고 생각했습니다. 그리고 그렇지 않은 것.
Darren H

답변:


5

망막 , 105 바이트

[1-8]
$*
^
/
iG`^(/[1KQRBNP]{8}){8}$
G`K
G`k
A`K.*K|k.*k
{2`N

2`B

2`R

1`Q

K

T`L`P
8`P

A`P
}T`l`L
^.

온라인으로 사용해보십시오! 링크에는 테스트 사례가 포함됩니다. 설명:

[1-8]
$*

숫자를 빈 정사각형으로 확장하면 1s로 표시됩니다 .

^
/
iG`^(/[1KQRBNP]{8}){8}$

/s 와 결합 된 8 개의 유효한 제곱 8 개 세트와 일치하지 않으면 입력을 삭제하십시오 . /검사를 단순화하기 위해 추가 접두사가 붙습니다.

G`K
G`k
A`K.*K|k.*k

흰색 또는 검은 색 왕이 없거나 두 가지 중 하나가 있으면 입력을 삭제하십시오.

{2`N

2`B

2`R

1`Q

K

화이트의 시작 부분이 여전히 있으면 삭제하십시오.

T`L`P

남은 흰색 조각을 폰으로 강등시킵니다.

8`P

유효한 흰색 폰을 삭제하십시오.

A`P

흰색 폰이 남아 있으면 입력을 삭제하십시오.

}T`l`L

검은 색 조각으로 다시 확인하십시오.

^.

줄을 삭제하지 않으면 정확한 값을 출력합니다.


6

자바 스크립트 (ES6), 168 (174) ... (155)

이 답변은 당황스러운 횟수로 편집되었습니다. 다행히도 현재 버전은 신뢰할 수 있고 괜찮은 수준입니다.


부울을 반환합니다.

s=>[...s].map(c=>++n%9?+c?n+=--c:a[i='pP/KkQqRrBbNn'.search(c),i&=i>4&a[i]>(i>6)||i]=-~a[i]:x+=c=='/',a=[x=n=0])&&!([p,P,s,k,K]=a,n-71|x-7|s|k*K-1|p>8|P>8)

형식화 및 의견

s => [...s].map(c =>                  // for each character 'c' in the FEN string 's':
  ++n % 9 ?                           //   if we haven't reached the end of a rank:
    +c ?                              //     if the character is a digit:
      n += --c                        //       advance the board pointer by c - 1 squares
    :                                 //     else:
      a[                              //       update the piece counter array:
        i =                           //         i = piece identifier (0 to 12)
          'pP/KkQqRrBbNn'.search(c),  //             with special case: '/' --> 2
        i &=                          //         we count it as a promoted pawn instead if:
          i > 4 &                     //           it's a Q, R, B or N and we already have
          a[i] > (i > 6) ||           //           2 of them for R, B, N or just 1 for Q
          i                           //           else, we keep the identifier unchanged
      ] = -~a[i]                      //         '-~' allows to increment 'undefined'
  :                                   //   else:
    x += c == '/',                    //     check that the expected '/' is there
  a = [                               //   initialize the piece counter array 'a'
    x =                               //   initialize the '/' counter 'x',
    n = 0 ]                           //   initialize the board pointer 'n'
) &&                                  // end of map()
!(                                    // now it's time to perform all sanity checks:
  [p, P, s, K, k] = a,                //   copy the 5 first entries of 'a' to new variables
  n - 71 |                            //   have we reached exactly the end of the board?
  x - 7 |                             //   have we identified exactly 7 ends of rank?
  s |                                 //   have we encountered any unexpected '/' character?
  k * K - 1 |                         //   do we have exactly one king on each side?
  p > 8 |                             //   no more than 8 black pawns, including promotions?
  P > 8)                              //   no more than 8 white pawns, including promotions?

테스트 사례


3

파이썬 3, 284 259236225247247234 바이트

import re
s=input()
t,c=s.split("/"),s.count;P=p=9;o=0
for x in"pqrnb":p-=max(0,c(x)-o);P-=max(0,c(x.upper())-o);o+=o<2
v=8==len(t)and all(8==sum(int(x)for x in re.sub("[A-z]","1",p))for p in t)and p>0<P and c('k')==c('K')==1
print(v)

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

모든 테스트 사례를 온라인으로 사용해보십시오!

Mr. Xcoder 덕분에 -11 바이트

Jonathan Allen 덕분에 -13 바이트

+22 나는 왕이 존재하는 것을 잊었다.

약간의 설명과 함께 반 멍청한 :

import re
string = input()
split = string.split("/")
count = string.count # find # of occurences of char in string
pawns = 9 # represents the # of pawns a player has out of the game... plus one, e.g. 1 is all in game, 2 is one out, 0 is invalid
PAWNS = 9 # would be 8, but then I would need >= instead of >
offset = 0 # default for pawns
for char in "pqrnb": # for each pawn, each queen over 1, and each rook/knight/bishop over 2 for each player
    # subtract one from the players 'pawns' var, which must end up 1 or greater to be valid
    # otherwise too many pawns/queens/etc of that player are on the board
    pawns -= max(0,count(char)-offset)
    PAWNS -= max(0,count(char.upper())-offset)
    offset += (offset 0 and PAWNS>0 and \ # make sure each player does not have an invalid number of pawns/q/n/b/r
    count('k')==count('K')==1 # correct # of kings
print(valid)

1
234 바이트 . 로 교체 ,p,P=9,9했습니다 ;P=p=9.
Mr. Xcoder

1
230 바이트 . 왜 불필요한 공백이 있었나요 for-loop/ :
씨 Xcoder

1
225 바이트 : p>0<P대신 p>0and P>05 바이트를 저장 하는 대신 사용할 수 있습니다 . 또한, 당신이 사용할 수도 p and P(대한 -3 바이트), 당신은 필요하지 않습니다 >0아닌 0 값은 파이썬에서 truthy 때문에,
씨 Xcoder

1
폰은 업그레이드 될 수 있으며, 스펙에는 7 개의 소문자 폰과 4 개의 루크가 있지만 내 눈에는 6 개의 소문자 'p'만 있다고 말합니다.
pizzapants184

1
o=0루프 이전 으로 초기화 o+=o<2하고 루프 본문의 끝에서 증가하여 13 바이트를 절약 할 수 있습니다 .
Jonathan Allan

2

PHP , 269 바이트

$t=($o=count_chars($a="$argn/"))[47]==8&$o[107]==1&$o[75]==1&9>($w=$u=$o[80])&9>$b=$l=$o[112];foreach([81,82,78,66]as$k=>$v){$z=$k?11:10;$b+=$x=$o[32+$v];$t&=$l+$x<$z;$w+=$x=$o[$v];$t&=$u+$x<$z;}$t&=$b<16&$w<16;for(;$c=$a[$n++];)$c<A?$c>0?$s+=$c:$t&=!$s-=8:++$s;echo$t;

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


2

자바 스크립트 (ES6) 181 172 174 바이트

f=([c,...s],n=1,o={p:0,P:0})=>c?c=='/'&&n%9?0:f(s,n+(+c||1),(o[c]=(o[c]||0)+(/[qrbn]/i.test(c)&&o[c]>1-/q/i.test(c)?!o[c>'a'?'p':'P']++:1),o)):o.p<9&o.P<9&n==72&o.k==1&o.K==1

언 골프 드 :

f=
  ([c,...s],                 //c is current character
   n=1,                      //n is current square, range [1-72] (board is 9x8 due to slashes)
   o={p:0,P:0}               //o holds piece counts
  )=>
  c?
    c=='/'&&n%9?0:           //ensure 8 squares per row
    f(s,
      n+(+c||1),             //increment n by the correct number of squares
      (o[c]=(o[c]||0)+(/[qrbn]/i.test(c)&&o[c]>1-/q/i.test(c)?!o[c>'a'?'p':'P']++:1),o)
                             //"depromote" extra queens, rooks, bishops, or knights
     ):
  o.p<9&o.P<9&               //no more than 8 pawns per side (accounting for promotions)
  o.k==1&o.K==1&             //each side has one and only one king  
  n==72                      //correct number of squares


1

파이썬 3 , 263 바이트

s=input()
n=0
for a in s.split('/'):n+=sum([int(c)if c in"123456789"else 1for c in a])
m=lambda k:{c:s.count(c)for c in s}.get(k,0)
p=[m("p"),m("P")]
for c in"rnbqRNGQ":b=c in"qQ";p[c<"Z"]+=m(c)+b-2if m(c)>2-b else 0
print((n==64)&(p[0]<9>p[1])&(m("K")>0<m("k")))

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

가장 작은 Python 제출은 아니지만 여전히 약속이 있다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.