Чи вірний цей рядок FEN?


12

Змагання

Напишіть програму або функцію, яка приймає рядок введення як функціональний параметр або з stdin і визначає, чи це дійсний рядок FEN .

Вхідні дані

Ви можете припустити, що вхід буде включати лише колись такі символи (залежно від регістру)
pkqrbnPKQRBN12345678/
. Довжина вводу завжди буде мінімум 1 символом і максимум 100 символів

Вихідні дані

Вихід повинен мати значення truthy / falsey. Це можуть бути будь-які значення, які ви бажаєте, якщо вони є послідовними (усі тритинні результати мають однаковий результат, усі результати фальси мають однаковий результат). У вас повинно бути рівно два різних можливих виходу.

Що вважається дійсним

Малі літери представляють собою чорні шматки, а великі літери - білі шматки.
Ви повинні переконатися, що в шаховій грі можливо, щоб фігури в поточній позиції існували.
У кожного гравця завжди буде рівно 1 король (к / к).
У кожного гравця може бути не більше 8 пішаків (p / P).
У кожного гравця зазвичай не більше 1 * королеви (q / Q).
У кожного гравця зазвичай не буде більше більше 2 * граків (r / r)
У кожного гравця зазвичай не більше 2 * лицарів (н / н).
У кожного гравця зазвичай не більше 2 * єпископів (б / б)
* Гравець законно ' просування 'пішака до будь-якого з цих чотирьох творів.
Загальна кількість пішаків, королеви, граків, лицарів та єпископів для кожного гравця ніколи не буде більше 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
Вихід помилковий
(чорний колір має 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
Вихід помилковий (2-й ранг має 9 квадратів / штук)

Введіть rnbqkbnr / pppppppp / 8/35/8/8 / PPPPPPPP / RNBQKBNR
Вихід Істинно
Завдяки Feersum та Arnauld за роз'яснення цього випадку (3 + 5 = 8)

Що таке FEN?

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 королев, поки кількість пішаків зменшиться для компенсації. Вам не потрібно турбуватися про те, щоб положення творів було законним чи незаконним, лише кількість творів.
Даррен Н

1
У вашому третьому тестовому випадку у чорного є 6 пішаків, а не 7, що робить його справжнім "(?)
pizzapants184

1
@DarrenH Позиція FEN, запропонована feersum, діє згідно ваших діючих правил. 35це просто незвичайний спосіб описати 8 порожніх квадратів.
Арнольд

1
@PatrickRoberts пішаків на перше чи останній ранг є дійсним для цілей цього завдання. Вам не потрібно обліковувати законність посади, лише кількість штук. Облік законності позиції (як, наприклад, обидва гравці перебувають під контролем) додає багато складності, тому я зрозумів, що ковдра «позиція не має значення» зрозуміліше, ніж дискусія про те, де провести межу того, що потрібно враховувати а що ні.
Даррен Н

Відповіді:


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 байт завдяки містеру Xcoder

-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.
Містер Xcoder

1
230 байт . Чому у вас виникли зайві місця у for-loop: /
Містер 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на кінці корпусу циклу.
Джонатан Аллан


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

Безголівки:

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, але я думаю, що це все ще має певні обіцянки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.