Ist diese Zeichenfolge gültig FEN?

12

Die Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die eine Zeichenfolge als Funktionsparameter oder von stdin empfängt und feststellt, ob es sich um eine gültige FEN- Zeichenfolge handelt.

Eingang

Sie können davon ausgehen, dass die Eingabe immer nur die folgenden Zeichen enthält (Groß- und Kleinschreibung beachten).
pkqrbnPKQRBN12345678/
Die Länge der Eingabe beträgt immer mindestens 1 Zeichen und höchstens 100 Zeichen

Ausgabe

Die Ausgabe sollte ein wahrer / falscher Wert sein. Dies können beliebige Werte sein, solange sie konsistent sind (alle echten Ergebnisse haben die gleiche Ausgabe, alle falschen Ergebnisse haben die gleiche Ausgabe). Sie sollten genau zwei verschiedene mögliche Ausgaben haben.

Was als gültig gilt

Kleinbuchstaben stehen für schwarze Teile, Großbuchstaben für weiße Teile.
Sie sollten sicherstellen, dass in einem Schachspiel die Figuren in der aktuellen Position vorhanden sein können.
Jeder Spieler hat immer genau 1 König (k / K).
Jeder Spieler darf nicht mehr als 8 Bauern (p / P) haben.
Jeder Spieler hat normalerweise nicht mehr als 1 * Dame (q / Q).
Jeder Spieler hat normalerweise nicht mehr als 2 * rooks (r / R)
erhält jeder Spieler hat in der Regel nicht mehr als 2 * Ritter (n / N)
in der Regel Jeder Spieler nicht mehr als 2 * Bischof (B / B) hat
* Es ist für einen Spieler legal ist zu " Werben Sie für eines dieser vier Teile um einen Bauern.
Die Gesamtzahl der Bauern, Königinnen, Türme, Ritter und Bischöfe pro Spieler wird niemals mehr als 15 betragen

Die Gesamtzahl der Teile plus leere Felder (durch Zahlen gekennzeichnet) sollte für jeden Rang immer genau 8 ergeben. Und es sollte immer genau 8 Ränge geben, die durch einen Schrägstrich voneinander getrennt sind.

Dinge, die Sie ignorieren können

Sie müssen sich nicht darum kümmern, ob es möglich ist, in die angegebene Position zu spielen, oder ob die Position legal ist, nur dass die Stücke in den angegebenen Mengen existieren können.
Sie können weitere Komplexitäten von FEN-Saiten wie Spielzug, Rochade-Rechte und En-Passant ignorieren.

Das ist Code Golf. Kürzestes Programm in Bytes gewinnt. Es gelten die üblichen Regelungslücken.

Testfälle

Eingabe rnbqkbnr / pppppppp / 8/8/8/8 / PPPPPPPP / RNBQKBNR
Ausgabe True

Eingang 2br2k1 / 1p2n1q1 / p2p2p1 / P1bP1pNp / 1BP2PnP / 1Q1B2P1 / 8 / 3NR2K
Ausgang Wahr

Eingang r2r2k1 / p3q2p / ppR3pr / rP4bp / 3p4 / 5B1P / P4PP1 / 3Q1RK1
Ausgang Falsch
(Schwarz hat 7 Bauern und 4 Türme - unmöglich)

Input 6k1 / pp3ppp / 4p3 / 2P3b1 / bPP3P1 / 3K4 / P3Q1q1
Output False (nur 7 Ränge)

Eingang 3r1rk1 / 1pp1bpp1 / 6p1 / pP1npqPn / 8 / 4N2P / P2PP3 / 1B2BP2 / R2QK2R
Ausgang False (9 Ränge)

Input 5n1k / 1p3r1qp / p3p3 / 2p1N2Q / 2P1R3 / 2P5 / P2r1PP1 / 4R1K1
Output False (2. Rang hat 9 Felder / Stücke)

Eingabe rnbqkbnr / pppppppp / 8/35/8/8 / PPPPPPPP / RNBQKBNR
Ausgabe True
Vielen Dank an Feersum und Arnauld für die Klärung dieses Falls (3 + 5 = 8)

Was ist FEN?

FEN ist eine Standardnotation zum Aufzeichnen der Position der Figuren auf einem Schachbrett. Bildnachweis http://www.chessgames.comBildbeschreibung hier eingeben

Darren H
quelle
"Jeder Spieler wird normalerweise nicht mehr als 1 * Dame haben" - klären Sie bitte, was als gültig gilt, da ich davon ausgehe, dass es egal ist, was als "normal" gilt. Gilt es für Weiß, neun Königinnen zu haben? Zehn Königinnen? Acht Bauern und zwei Königinnen? Null Könige? Ein nicht geförderter Bauer auf dem ersten oder letzten Rang?
Anders Kaseorg
@AndersKaseorg * It is legal for a player to 'promote' a pawn to any of these four pieces.Der Spieler darf bis zu 9 Damen haben, solange die Anzahl der Bauern zum Ausgleich verringert wird. Sie müssen sich keine Gedanken darüber machen, ob die Teile legal oder illegal sind, sondern nur über die Anzahl der Teile.
Darren H
1
In Ihrem dritten Testfall hat Schwarz 6 Bauern, nicht 7, was es zu einem "Wahren" (?)
Macht
1
@DarrenH Die von feersum vorgeschlagene FEN-Position ist gemäß Ihren aktuellen Regeln gültig. 35ist nur eine ungewöhnliche Art, 8 leere Quadrate zu beschreiben.
Arnauld
1
@PatrickRoberts Bauern auf dem ersten oder letzten Rang sind für den Zweck dieser Herausforderung gültig. Sie müssen nicht die Legalität einer Position berücksichtigen, sondern nur die Stückzahl. Die Berücksichtigung der Rechtmäßigkeit einer Position (z. B., dass beide Spieler in Schach sind) erhöht die Komplexität erheblich, sodass ich dachte, dass eine Decke aus "Position spielt keine Rolle" klarer ist als eine Debatte darüber, wo die Linie der berücksichtigten Bedürfnisse gezogen werden soll und was nicht.
Darren H

Antworten:

5

Netzhaut , 105 Bytes

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

Probieren Sie es online! Link enthält Testfälle. Erläuterung:

[1-8]
$*

Erweitern Sie die Ziffern zu leeren Quadraten, die wir mit 1s bezeichnen.

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

Löschen Sie die Eingabe, wenn sie nicht mit 8 Mengen von 8 gültigen Quadraten übereinstimmt, die mit /s verbunden sind. (Ein Extra /wird vorangestellt, um die Prüfung zu vereinfachen.)

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

Löschen Sie die Eingabe, wenn sie keinen weißen oder keinen schwarzen König hat oder wenn sie zwei von beiden hat.

{2`N

2`B

2`R

1`Q

K

Lösche die Startsteine ​​von Weiß, wenn sie noch da sind.

T`L`P

Reduziere alle verbleibenden weißen Teile auf Bauern.

8`P

Löschen Sie die gültigen weißen Bauern.

A`P

Löschen Sie die Eingabe, wenn noch weiße Bauern übrig sind.

}T`l`L

Überprüfen Sie noch einmal, aber mit den schwarzen Stücken.

^.

Gibt einen Wahrheitswert aus, sofern die Zeile nicht gelöscht wurde.

Neil
quelle
6

JavaScript (ES6), 168 174 ... 155

Diese Antwort wurde bereits mehrmals peinlich bearbeitet. Hoffentlich ist die aktuelle Version sowohl zuverlässig als auch anständig golfen.


Gibt einen Booleschen Wert zurück.

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)

Formatiert und kommentiert

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?

Testfälle

Arnauld
quelle
3

Python 3, 284 259 236 225 247 234 Bytes

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)

Probieren Sie es online!

Probieren Sie es online mit allen Testfällen!

-11 Bytes dank Mr. Xcoder

-13 Bytes dank Jonathan Allen

+22 Ich habe vergessen, dass Könige existieren.

Semi-ungolfed mit einer Erklärung:

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)
Pizzapants184
quelle
1
234 Bytes . Ich ersetzte ,p,P=9,9mit ;P=p=9.
Mr. Xcoder
1
230 Bytes . Warum haben Sie unnötige Leerzeichen in der for-loop: /
Mr. Xcoder
1
225 Bytes : Sie können p>0<Panstelle von auch p>0and P>05 Bytes speichern. Alternativ hätten Sie p and P(für -3 Bytes) das brauchen Sie nicht >0, denn in Python sind Werte ungleich Null wahr
Mr. Xcoder
1
Bauern können verbessert werden, die Spezifikation besagt, dass es 7 Kleinbauern und 4 Türme gibt, während meine Augen nur 6 Kleinbauern sehen.
Pizzapants184
1
Sie können 13 Bytes sparen, indem Sie o=0vor der Schleife mit initialisieren und o+=o<2am Ende des Schleifenkörpers mit inkrementieren .
Jonathan Allan
2

PHP , 269 Bytes

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

Probieren Sie es online!

Jörg Hülsermann
quelle
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

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

Rick Hitchcock
quelle
1

Python 3 , 263 Bytes

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

Probieren Sie es online!

Nicht die kleinste Python-Einreichung, aber ich denke, sie ist noch vielversprechend.

MooseOnTheRocks
quelle