Эта строка действительна FEN?


12

Соревнование

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

вход

Можно предположить, что ввод будет включать только следующие символы (с учетом регистра)
pkqrbnPKQRBN12345678/
. Длина ввода всегда будет составлять не менее 1 символа и не более 100 символов.

Выход

Вывод должен быть истинным / ложным значением. Это могут быть любые значения, которые вы хотите, если они согласованы (все достоверные результаты имеют одинаковый вывод, все ложные результаты имеют одинаковый вывод). У вас должно быть ровно два разных возможных выхода.

Что считается действительным

Строчные буквы представляют черные фигуры, прописные буквы представляют белые фигуры.
Вы должны убедиться, что в игре в шахматы фигуры в текущей позиции могут существовать.
У каждого игрока всегда будет ровно 1 король (k / K).
У каждого игрока может быть не более 8 пешек (p / P).
У каждого игрока обычно не более 1 * королевы (q / Q).
У каждого игрока обычно не более чем 2 * грачей (г / R)
Каждый игрок обычно имеет не более 2 * рыцарей (N / N)
Каждый игрок обычно имеет не более 2 * епископов (B / B)
* это законно для игрока к ' продвиньте пешку к любому из этих четырех частей.
Общее количество пешек, ферзей, грачей, рыцарей и слонов для каждого игрока никогда не будет превышать 15

Общее количество фигур плюс пустые квадраты (обозначенные цифрами) всегда должно составлять ровно 8 для каждого ранга. И всегда должно быть ровно 8 рангов, разделенных косой чертой.

Вещи, которые вы можете игнорировать

Вам не нужно беспокоиться о том, возможно ли сыграть в обозначенной позиции или, если позиция законна, только то, что фигуры могут существовать в указанных количествах.
Вы можете игнорировать дальнейшие сложности строк FEN, такие как ход игрока, права рокировки и en passant.

Это код гольф. Самая короткая программа в байтах побеждает. Обычные лазейки и правила применяются.

Тестовые случаи

Входные данные 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
Выход False (только 7 рангов)

Вход 3r1rk1 / 1pp1bpp1 / 6p1 / pP1npqPn / 8 / 4N2P / P2PP3 / 1B2BP2 / R2QK2R
Выход False (9 рангов)

Вход 5n1k / 1p3r1qp / p3p3 / 2p1N2Q / 2P1R3 / 2P5 / P2r1PP1 / 4R1K1
Выход False (2-й ранг имеет 9 квадратов / штук)

Входные данные rnbqkbnr / pppppppp / 8/35/8/8 / PPPPPPPP / RNBQKBNR
Выходные данные True
Спасибо Feersum и Arnauld за разъяснение этого случая (3 + 5 = 8)

Что такое FEN?

FEN - это стандартное обозначение для записи положения фигур на шахматной доске. Изображение предоставлено http://www.chessgames.comвведите описание изображения здесь


«У каждого игрока обычно не более 1 * королевы» - уточните, что считается действительным, поскольку я предполагаю, что не имеет значения, что считается «обычным». Действительно ли у белых девять королев? Десять королев? Восемь пешек и две королевы? Ноль королей? Не продвинутая пешка на первом или последнем звании?
Андерс Касеорг

@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.
Мистер Кскодер

1
230 байтов . Почему у вас были лишние пробелы в for-loop: /
Мистер Xcoder

1
225 байт : вы можете использовать p>0<Pвместо того, p>0and P>0чтобы сохранить 5 байт тоже. В качестве альтернативы, вы могли бы использовать p and P(для -3 байта), вам не нужно >0, потому что ненулевые значения верны в Python
г-н Xcoder

1
Пешки могут быть улучшены, спецификация говорит, что есть 7 строчных пешек и 4 ладьи, в то время как мои глаза видят только 6 строчных p.
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

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, но я думаю, что оно все еще имеет некоторое обещание.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.