Chuỗi này có hợp lệ FEN không?


12

Các thách thức

Viết chương trình hoặc hàm lấy đầu vào chuỗi làm tham số hàm hoặc từ stdin và xác định xem đó có phải là chuỗi FEN hợp lệ không .

Đầu vào

Bạn có thể giả sử đầu vào sẽ chỉ bao gồm các ký tự sau (phân biệt chữ hoa chữ thường)
pkqrbnPKQRBN12345678/
Độ dài của đầu vào sẽ luôn tối thiểu là 1 ký tự và tối đa 100 ký tự

Đầu ra

Đầu ra phải là một giá trị trung thực / falsey. Đây có thể là bất kỳ giá trị nào bạn muốn miễn là chúng phù hợp (tất cả các kết quả trung thực có cùng một đầu ra, tất cả các kết quả falsey đều có cùng một đầu ra). Bạn nên có chính xác hai đầu ra khác biệt có thể.

Những gì được coi là hợp lệ

Chữ thường đại diện cho các mảnh màu đen, chữ in hoa đại diện cho các mảnh màu trắng.
Bạn nên đảm bảo có thể trong một ván cờ để các quân cờ ở vị trí hiện tại tồn tại.
Mỗi người chơi sẽ luôn có chính xác 1 vua (k / K)
Mỗi người chơi có thể có không quá 8 pawns (p / P)
Mỗi người chơi thường sẽ có không quá 1 * nữ hoàng (q / Q)
Mỗi người chơi thường sẽ không có nhiều hơn hơn 2 * rooks (r / R)
Mỗi người chơi thường sẽ có không quá 2 * hiệp sĩ (n / N)
Mỗi người chơi thường sẽ có không quá 2 * giám mục (b / B)
* Người chơi phải hợp pháp ' quảng bá 'một con tốt cho bất kỳ trong bốn phần này.
Tổng số pawns, nữ hoàng, tân binh, hiệp sĩ và giám mục cho mỗi người chơi sẽ không bao giờ nhiều hơn 15

Tổng số mảnh cộng với hình vuông trống (được biểu thị bằng số) phải luôn luôn thêm tối đa 8 cho mỗi cấp bậc. Và phải luôn luôn có chính xác 8 cấp bậc, cách nhau bởi một dấu gạch chéo về phía trước.

Những điều bạn có thể bỏ qua

Bạn không cần quan tâm đến việc liệu có thể chơi ở vị trí được biểu thị hay không, hoặc nếu vị trí đó là hợp pháp, chỉ có các phần có thể tồn tại với số lượng được đưa ra.
Bạn có thể bỏ qua sự phức tạp hơn nữa của các chuỗi FEN như lượt người chơi, quyền castling và en passant.

Đây là mã golf. Chương trình ngắn nhất trong byte thắng. Lỗ hổng thông thường và quy tắc áp dụng.

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

Đầu vào rnbqkbnr / pppppppp / 8/8/8/8 / PPPPPPPP / RNBQKBNR
Đầu ra Đúng

Đầu vào 2br2k1 / 1p2n1q1 / p2p2p1 / P1bP1pNp / 1BP2PnP / 1Q1B2P1 / 8 / 3NR2K
Đầu ra Đúng

Đầu vào r2r2k1 / p3q2p / ppR3pr / rP4bp / 3p4 / 5B1P / P4PP1 / 3Q1RK1
Đầu ra Sai
(màu đen có 7 pawns và 4 rooks - không thể)

Nhập 6k1 / pp3ppp / 4p3 / 2P3b1 / bPP3P1 / 3K4 / P3Q1q1
Đầu ra Sai (chỉ có 7 cấp)

Đầu vào 3r1rk1 / 1pp1bpp1 / 6p1 / pP1npqPn / 8 / 4N2P / P2PP3 / 1B2BP2 / R2QK2R
Đầu ra Sai (9 bậc)

Nhập 5n1k / 1p3r1qp / p3p3 / 2p1N2Q / 2P1R3 / 2P5 / P2r1PP1 / 4R1K1
Đầu ra Sai (xếp hạng 2 có 9 ô vuông / miếng)

Đầu vào rnbqkbnr / pppppppp / 8/35/8/8 / PPPPPPPP / RNBQKBNR
Đầu ra Đúng
Cảm ơn Feersum và Arnauld để làm rõ trường hợp này (3 + 5 = 8)

FEN là gì?

FEN là một ký hiệu chuẩn để ghi vị trí của các quân cờ trên bàn cờ. Tín dụng hình ảnh http://www.chessgames.comnhập mô tả hình ảnh ở đây


Mỗi người chơi thường sẽ không có nhiều hơn 1 * nữ hoàng Hoàng đế Hãy làm rõ những gì được coi là hợp lệ, vì tôi cho rằng nó không quan trọng như những gì được coi là thông thường. Có hợp lệ cho màu trắng để có chín nữ hoàng? Mười nữ hoàng? Tám con tốt và hai nữ hoàng? Không có vua? Một con tốt không được xếp hạng trên thứ hạng đầu tiên hoặc cuối cùng?
Anders Kaseorg

@AndersKaseorg * It is legal for a player to 'promote' a pawn to any of these four pieces.Người chơi có thể có tới 9 nữ hoàng miễn là số lượng con tốt bị giảm để bù lại. Bạn không cần phải lo lắng về vị trí của các mảnh là hợp pháp hoặc bất hợp pháp, chỉ có số lượng các mảnh.
Darren H

1
Trong trường hợp thử nghiệm thứ ba của bạn, màu đen có 6 con tốt chứ không phải 7, biến nó thành 'Đúng' (?)
pizzapants184

1
@DarrenH Vị trí FEN được đề xuất bởi frageum là hợp lệ theo các quy tắc hiện tại của bạn. 35chỉ là một cách khác thường để mô tả 8 ô vuông trống.
Arnauld

1
@PatrickRoberts cầm đồ ở hạng đầu tiên hoặc cuối cùng hợp lệ cho mục đích của thử thách này. Bạn không cần tính đến tính hợp pháp của một vị trí, chỉ cần số lượng các mảnh. Việc tính toán tính hợp pháp của một vị trí (chẳng hạn như cả hai người chơi đang được kiểm tra) làm tăng thêm sự phức tạp, vì vậy tôi đã hình dung ra một "vị trí không quan trọng" rõ ràng hơn là một cuộc tranh luận về việc vẽ ra những gì cần phải giải quyết và những gì không.
Darren H

Câu trả lời:


5

Võng mạc , 105 byte

[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
^.

Hãy thử trực tuyến! Liên kết bao gồm các trường hợp thử nghiệm. Giải trình:

[1-8]
$*

Mở rộng các chữ số thành các ô vuông trống, mà chúng tôi biểu thị bằng 1s.

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

Xóa đầu vào nếu nó không khớp với 8 bộ 8 ô vuông hợp lệ được nối với /s. (Một phần bổ sung /được thêm tiền tố để đơn giản hóa việc kiểm tra.)

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

Xóa đầu vào nếu nó không có vua trắng hoặc đen hoặc nếu có hai trong số đó.

{2`N

2`B

2`R

1`Q

K

Xóa các phần bắt đầu của màu trắng, nếu chúng vẫn còn ở đó.

T`L`P

Hạ cấp bất kỳ mảnh trắng còn lại để cầm đồ.

8`P

Xóa các con tốt trắng hợp lệ.

A`P

Xóa đầu vào nếu có bất kỳ con tốt trắng nào còn sót lại.

}T`l`L

Kiểm tra lại nhưng với các mảnh màu đen.

^.

Xuất ra một giá trị trung thực trừ khi dòng bị xóa.


6

JavaScript (ES6), 168 174 ... 155

Câu trả lời này đã được chỉnh sửa một số lần lúng túng. Hy vọng rằng, phiên bản hiện tại là đáng tin cậy và vừa chơi golf.


Trả về một boolean.

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)

Định dạng và nhận xét

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?

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


3

Python 3, 284 259 236 225 247 234 byte

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)

Hãy thử trực tuyến!

Hãy thử trực tuyến với tất cả các trường hợp thử nghiệm!

-11 byte nhờ ông Xcoder

-13 byte nhờ Jonathan Allen

+22 Tôi đã quên các vị vua tồn tại.

Bán vô chủ với một số lời giải thích:

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 byte . Tôi thay thế ,p,P=9,9bằng ;P=p=9.
Ông Xcoder

1
230 byte . Tại sao bạn có không gian không cần thiết trong for-loop: /
Ông Xcoder

1
225 byte : Bạn có thể sử dụng p>0<Pthay vì p>0and P>0để lưu 5 byte. Ngoài ra, bạn có thể đã sử dụng p and P(cho -3 byte), bạn không cần >0, bởi vì các giá trị khác không là sự thật trong Python
Ông Xcoder

1
Chân có thể được nâng cấp, thông số kỹ thuật nói rằng có 7 pawns chữ thường và 4 rooks, trong khi mắt tôi chỉ nhìn thấy 6 chữ thường.
pizzapants184

1
Bạn có thể lưu 13 byte bằng cách khởi tạo o=0trước vòng lặp và tăng dần o+=o<2ở cuối thân vòng lặp.
Jonathan Allan

2

PHP , 269 byte

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

Hãy thử trực tuyến!


2

JavaScript (ES6), 181 172 174 byte

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

Ung dung:

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

Python 3 , 263 byte

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

Hãy thử trực tuyến!

Không phải là đệ trình Python nhỏ nhất, nhưng tôi nghĩ nó vẫn có một số lời hứa.

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.