この文字列は有効なFENですか?


12

チャレンジ

文字列入力を関数パラメーターとして、またはstdinから取得し、それが有効なFEN文字列かどうかを判断するプログラムまたは関数を作成します。

入力

入力には次の文字のみが含まれると想定できます(大文字と小文字が区別されます)
pkqrbnPKQRBN12345678/
入力の長さは常に最小1文字、最大100文字です。

出力

出力は、真偽値でなければなりません。これらは、一貫している限り、任意の値にすることができます(すべての真実の結果は同じ出力を持ち、すべての偽の結果は同じ出力を持ちます)。正確に2つの可能な出力が必要です。

有効とみなされるもの

小文字は黒い部分を表し、大文字は白い部分を表します。
チェスのゲームで、現在の位置にあるピースが存在することを確認する必要があります。
各プレイヤーは常に正確に1つのキング(k / K)を
持ちます。各プレイヤーは8個以下のポーン(p / P)を
持ちます。各プレイヤーは通常1 *クイーン以下(q / Q)を
持ちます。 2 *を超えるルーク(r / R)
各プレイヤーは通常2 *を超える騎士(n / N)を
持たない各プレイヤーは通常2 *を超える司教(b / B)を持たない*
プレイヤーが「これら4つのピースのいずれかにポーンをプロモートします。
各プレイヤーのポーン、クイーン、ルーク、ナイト、ビショップの合計が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
出力 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 *クイーン以下しかありません」-何が「通常」と見なされるかは関係ないと仮定しているため、何が有効と見なされるかを明確にしてください。白人が9人の女王を持つことは有効ですか?テンクイーン?8つのポーンと2つのクイーン?ゼロキング?最初のランクまたは最後のランクのプロモーションされていないポーン?
アンデルスカセオルグ

@AndersKaseorg * It is legal for a player to 'promote' a pawn to any of these four pieces.プレイヤーは、ポーンの数を減らして補償する限り、最大で9人のクイーンを持つことができます。ピースの数だけで、ピースの位置が合法であるか違法であるかを心配する必要はありません。
ダレンH

1
3番目のテストケースでは、黒は7ではなく6個のポーンを持ち、 'True'(?)になります
pizzapants184

1
@DarrenH feersumによって提案されたFENポジションは、現在のルールに従って有効です。358個の空の正方形を記述するための異常な方法です。
アーナルド

1
最初または最後のランク上の@PatrickRobertsポーンがあり、この課題の目的のために有効。ポジションの合法性を考慮する必要はなく、ピースの量のみを考慮する必要があります。ポジションの合法性(両方のプレーヤーがチェックされているなど)を考慮すると、多くの複雑さが追加されます。そして、何がしません。
ダレン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]
$*

数字を空の正方形に展開し1ます。これはs を使用して表します。

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

入力が/sで結合された8つの有効な正方形の8セットに一致しない場合は、入力を削除します。(/チェックを簡単にするために、追加のプレフィックスが付けられます。)

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

白または黒のキングがない場合、または入力が2つある場合は、入力を削除します。

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

オンラインでお試しください!

すべてのテストケースでオンラインでお試しください!

Mr. Xcoderのおかげで-11バイト

ジョナサンアレンのおかげで-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:/
Mr. Xcoder

1
225バイト:5バイトを節約するp>0<P代わりにp>0and P>0を使用することもできます。また、あなたが使用している可能性p and P(のために-3バイト)、あなたは必要としない>0非ゼロ値は、Pythonでtruthyているので、
氏Xcoder

1
ポーンはアップグレードできます。仕様では、7つの小文字のポーンと4つのルークがありますが、私の目では6つの小文字の「p」しか見えません。
pizzapants184

1
o=0ループの前で初期化しo+=o<2、ループの本体の終わりで増分 することにより、13バイトを節約できます。
ジョナサンアラン


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サブミッションではありませんが、まだいくつかの見込みがあると思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.