สตริงนี้เป็น FEN ที่ถูกต้องหรือไม่


12

ความท้าทาย

เขียนโปรแกรมหรือฟังก์ชั่นซึ่งรับอินพุตสตริงเป็นพารามิเตอร์ฟังก์ชันหรือจาก stdin และพิจารณาว่าเป็นสตริงFEN ที่ถูกต้องหรือไม่

อินพุต

คุณสามารถสันนิษฐานได้ว่าอินพุตจะมีอักขระต่อไปนี้ (ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่)
pkqrbnPKQRBN12345678/
ความยาวของอินพุตจะต้องมีอย่างน้อย 1 ตัวอักษรและสูงสุด 100 ตัวอักษร

เอาท์พุต

ผลลัพธ์ควรเป็นค่าจริง / เท็จ เหล่านี้สามารถเป็นค่าใด ๆ ที่คุณต้องการตราบใดที่พวกเขามีความสอดคล้องกัน (ผลความจริงทั้งหมดมีผลลัพธ์ที่เหมือนกันผลลัพธ์เท็จทั้งหมดมีผลลัพธ์ที่เหมือนกัน) คุณควรมีเอาต์พุตที่แตกต่างกันสองแบบ

สิ่งที่นับว่าถูกต้อง

ตัวอักษรตัวพิมพ์เล็กแทนชิ้นส่วนสีดำตัวอักษรตัวพิมพ์ใหญ่แทนชิ้นส่วนสีขาว
คุณควรตรวจสอบให้แน่ใจว่าเป็นไปได้ในเกมหมากรุกสำหรับชิ้นส่วนที่อยู่ในตำแหน่งปัจจุบัน
ผู้เล่นแต่ละคนจะมี 1 ราชาเสมอ (k / K)
ผู้เล่นแต่ละคนอาจมีไม่เกิน 8 เบี้ย (p / P)
ผู้เล่นแต่ละคนมักจะมีไม่เกิน 1 * ราชินี (q / Q)
ผู้เล่นแต่ละคนจะไม่มีอีกต่อไป มากกว่า 2 * rooks (r / R)
ผู้เล่นแต่ละคนจะมีอัศวินไม่เกิน 2 * (n / N)
ผู้เล่นแต่ละคนมักจะมีไม่เกิน 2 * bishops (b / B)
* มันถูกกฎหมายสำหรับผู้เล่นที่ ' ส่งเสริม 'จำนำให้กับสี่ชิ้นใด ๆ เหล่านี้
จำนวนเบี้ย, ควีนส์, rooks, อัศวินและบาทหลวงสำหรับผู้เล่นแต่ละคนจะไม่เกิน 15

จำนวนชิ้นรวมกับช่องว่างที่ว่างเปล่า (แสดงโดยตัวเลข) ควรบวกได้สูงสุด 8 สำหรับแต่ละอันดับ และควรมีตำแหน่ง 8 ตำแหน่งเสมอคั่นด้วยเครื่องหมายสแลช

สิ่งที่คุณสามารถเพิกเฉย

คุณไม่จำเป็นต้องกังวลกับตัวเองว่าเป็นไปได้หรือไม่ที่จะเล่นลงในตำแหน่งที่แสดงหรือหากตำแหน่งนั้นถูกกฎหมายเพียงชิ้นส่วนเท่านั้นที่สามารถมีอยู่ในปริมาณที่กำหนด
คุณสามารถละเว้นความซับซ้อนเพิ่มเติมของสาย FEN เช่นเทิร์นเพลเยอร์, ​​สิทธิ์ในการเหวี่ยงและ en passant

นี่คือรหัสกอล์ฟ โปรแกรมที่สั้นที่สุดเป็นไบต์ชนะ ใช้ช่องโหว่และกฎตามปกติ

กรณีทดสอบ

อินพุต rnbqkbnr / pppppppp / 8/8/8/8 / PPPPPPPP / RNBQKBNR
เอาต์พุตจริง

อินพุต 2br2k1 / 1p2n1q1 / p2p2p1 / P1bP1pNp / 1BP2PnP / 1Q1B2P1 / 8 / 3NR2K
เอาต์พุตจริง

อินพุต r2r2k1 / p3q2p / ppR3pr / rP4bp / 3p4 / 5B1P / P4PP1 / 3Q1RK1
เอาต์พุตเท็จ
(สีดำมี 7 เบี้ยและ 4 rooks - เป็นไปไม่ได้)

อินพุต 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
เอาต์พุตเท็จ (อันดับที่ 2 มี 9 สี่เหลี่ยม / ชิ้น)

อินพุต rnbqkbnr / pppppppp / 8/35/8/8 / PPPPPPPP / RNBQKBNR
เอาท์พุทจริง
ขอบคุณ Feersum และ Arnauld สำหรับชี้แจงกรณีนี้ (3 + 5 = 8)

เฟนคืออะไร

FENเป็นสัญกรณ์มาตรฐานสำหรับการบันทึกตำแหน่งของชิ้นส่วนบนกระดานหมากรุก เครดิตภาพhttp://www.chessgames.comป้อนคำอธิบายรูปภาพที่นี่


“ ผู้เล่นแต่ละคนมักจะมีไม่เกิน 1 * ราชินี” - โปรดชี้แจงสิ่งที่นับว่าถูกต้องเนื่องจากฉันคิดว่ามันไม่สำคัญว่าจะนับว่า "ปกติ" สีขาวนั้นมีเก้าราชินีหรือไม่ สิบราชินี แปดเบี้ยและสองราชินี ไม่มีราชา จำนำไม่ได้รับการส่งเสริมในอันดับแรกหรือสุดท้าย?
Anders Kaseorg

@AndersKaseorg * It is legal for a player to 'promote' a pawn to any of these four pieces.ผู้เล่นอาจมีมากถึง 9 ราชินีตราบใดที่จำนวนเบี้ยลดลงเพื่อชดเชย คุณไม่จำเป็นต้องกังวลเกี่ยวกับตำแหน่งของชิ้นส่วนที่ถูกกฎหมายหรือผิดกฎหมายเพียงจำนวนชิ้น
Darren H

1
ในกรณีทดสอบครั้งที่สามของคุณสีดำมีเบี้ย 6 ตัวไม่ใช่ 7 ทำให้มันเป็น 'จริง' (?)
pizzapants184

1
@DarrenH ตำแหน่ง FEN ที่เสนอโดย feersum นั้นถูกต้องตามกฎปัจจุบันของคุณ 35เป็นเพียงวิธีที่ผิดปกติในการอธิบายช่องว่าง 8 ช่อง
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}$

ลบอินพุตถ้ามันไม่ตรงกับ 8 ชุด 8 สี่เหลี่ยมที่ถูกต้องเข้าร่วมกับ/s (ส่วนเสริม/จะถูกนำหน้าเพื่อทำให้การตรวจสอบง่ายขึ้น)

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

JavaScript (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

Python 3, 284 259 236 225 247 234 ไบต์

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)

ลองออนไลน์!

ลองใช้ออนไลน์กับทุกกรณีทดสอบ!

-11 ไบต์ขอบคุณ Mr. Xcoder

-13 ไบต์ขอบคุณ Jonathan Allen

+22 ฉันลืมกษัตริย์ไปแล้ว

กึ่ง ungolfed ด้วยคำอธิบายบางอย่าง:

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: /
Mr. Xcoder

1
225 ไบต์ : คุณสามารถใช้p>0<Pแทนp>0and P>0การบันทึก 5 ไบต์ได้เช่นกัน หรือคุณอาจใช้p and P(สำหรับ -3 ไบต์) คุณไม่ต้องการ>0เพราะค่าที่ไม่ใช่ศูนย์นั้นเป็นความจริงใน Python
Mr. Xcoder

1
สามารถอัปเกรดเบี้ยได้สเป็คบอกว่ามีเบี้ยเบี้ยว 7 ตัวและ 4 รู๊คในขณะที่ดวงตาของฉันเห็นเพียง 6 ตัวพิมพ์เล็ก
pizzapants184

1
คุณสามารถบันทึก 13 ไบต์โดยเริ่มต้นด้วยo=0ก่อนลูปและเพิ่มขึ้นด้วย o+=o<2ในตอนท้ายของร่างกายของลูป
Jonathan Allan


2

JavaScript (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

Ungolfed:

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 ไบต์

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.