Bu dize FEN geçerli mi?


12

Meydan okuma

Bir dize girişini işlev parametresi olarak mı yoksa stdin'den alan ve geçerli bir FEN dizesi mi olduğunu belirleyen bir program veya işlev yazın .

Giriş

Girişin yalnızca aşağıdaki karakterleri içereceğini varsayabilirsiniz (büyük / küçük harfe duyarlı)
pkqrbnPKQRBN12345678/
Girişin uzunluğu her zaman en az 1 karakter ve en fazla 100 karakter olacaktır

Çıktı

Çıktı gerçek / falsey bir değer olmalıdır. Bunlar tutarlı oldukları sürece istediğiniz herhangi bir değer olabilir (tüm doğru sonuçlar aynı çıktıya, tüm falsey sonuçları aynı çıktıya sahiptir). Tam olarak iki farklı olası çıktınız olmalıdır.

Geçerli sayılan

Küçük harfler siyah parçaları, büyük harfler beyaz parçaları temsil eder.
Mevcut pozisyondaki parçaların var olabilmesi için bir satranç oyununda mümkün olduğundan emin olmalısınız.
Her oyuncunun her zaman tam olarak 1 kralı (k / K) olacaktır.
Her oyuncunun en fazla 8 piyonu (p / P) olabilir.
Her oyuncunun genellikle en fazla 1 * kraliçesi (q / Q)
olmayacaktır. 2 * rooks (R / R) daha
Her oyuncu, genellikle en fazla 2 * şövalyeleri (n / H) sahip olacak
Her oyuncu, genellikle en fazla 2 * piskoposlarını (b / B) sahip olacaktır
* Bu 'için bir oyuncu için yasal bu dört parçadan herhangi birine bir piyon tanıtmak.
Her oyuncu için toplam piyon, kraliçe, kale, şövalye ve piskopos asla 15'ten fazla olmayacak

Toplam parça sayısı artı boş kareler (sayılarla gösterilir) her bir sıralama için her zaman tam olarak 8'e kadar eklemelidir. Ve her zaman tam bir eğik çizgi ile ayrılmış tam olarak 8 rütbe olmalıdır.

Göz ardı edebileceğiniz şeyler

Belirtilen pozisyonda oynamanın mümkün olup olmadığı ya da pozisyon yasal ise, sadece parçaların verilen miktarlarda var olabileceği konusunda endişelenmenize gerek yoktur.
Oyuncu dönüşü, oyuncu hakları ve geçiş hakkı gibi FEN dizelerinin diğer karmaşıklıklarını göz ardı edebilirsiniz.

Bu kod golf. Bayt cinsinden en kısa program kazanır. Her zamanki boşluklar ve kurallar geçerlidir.

Test Durumları

Giriş rnbqkbnr / pppppppp / 8/8/8/8 / PPPPPPPP / RNBQKBNR
Çıkışı Doğru

Giriş 2br2k1 / 1p2n1q1 / p2p2p1 / P1bP1pNp / 1BP2PnP / 1Q1B2P1 / 8 / 3NR2K
Çıkış Doğru

Giriş r2r2k1 / p3q2p / ppR3pr / rP4bp / 3p4 / 5B1P / P4PP1 / 3Q1RK1
Çıkışı Yanlış
(siyah 7 piyon ve 4 kaleye sahiptir - imkansız)

Giriş 6k1 / pp3ppp / 4p3 / 2P3b1 / bPP3P1 / 3K4 / P3Q1q1
Çıkışı Yanlış (sadece 7 sıralama)

Giriş 3r1rk1 / 1pp1bpp1 / 6p1 / pP1npqPn / 8 / 4N2P / P2PP3 / 1B2BP2 / R2QK2R
Çıkışı Yanlış (9 sıralama)

Giriş 5n1k / 1p3r1qp / p3p3 / 2p1N2Q / 2P1R3 / 2P5 / P2r1PP1 / 4R1K1
Çıkışı Yanlış (2. sırada 9 kare / adet var)

Giriş rnbqkbnr / pppppppp / 8/35/8/8 / PPPPPPPP / RNBQKBNR
Çıkışı Doğru
Bu durumda açıklık için Feersum ve Arnauld sayesinde (3 + 5 = 8)

FEN nedir?

FEN , parçaların satranç tahtasındaki konumunu kaydetmek için standart bir gösterimdir. Resim kredisi http://www.chessgames.comresim açıklamasını buraya girin


“Her oyuncunun genellikle en fazla 1 * kraliçesi” olmaz - lütfen neyin geçerli sayıldığını netleştirin, çünkü neyin “olağan” sayıldığının önemli olmadığını varsayarım. Beyazın dokuz kraliçesi olması geçerli midir? On kraliçe mi? Sekiz piyon ve iki kraliçe mi? Sıfır krallar mı? Birinci veya son rütbede uzlaştırılmamış bir piyon mu?
Anders Kaseorg

@AndersKaseorg * It is legal for a player to 'promote' a pawn to any of these four pieces.Oyuncu piyon sayısı telafi etmek için azaldığı sürece 9 taneye kadar kraliçeye sahip olabilir. Parçaların yasal veya yasadışı olmaları hakkında endişelenmenize gerek yok, sadece parça sayısı.
Darren H

1
Üçüncü test durumunuzda, siyahın 7 değil 6 piyonu vardır, bunu 'Gerçek' (?)
Yapar

1
@DarrenH Feersum tarafından önerilen FEN konumu, mevcut kurallarınıza göre geçerlidir. 358 boş kareyi tanımlamanın alışılmadık bir yoludur.
Arnauld

1
İlk veya son rütbede bulunan @PatrickRoberts piyonları bu meydan okuma için geçerlidir. Bir pozisyonun yasallığını, sadece parça sayısını hesaba katmanıza gerek yoktur. Bir pozisyonun yasallığını (her iki oyuncunun kontrol altında olması gibi) muhasebeleştirmesi çok karmaşıklık getirir, bu yüzden 'pozisyonun bir önemi yok' battaniyesinin, muhasebeleştirilen ihtiyaçların çizgisini nereye çekeceğine dair bir tartışmadan daha net olduğunu düşündüm ve olmayan.
Darren H

Yanıtlar:


5

Retina , 105 bayt

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

Çevrimiçi deneyin! Bağlantı, test senaryolarını içerir. Açıklama:

[1-8]
$*

Rakamları, 1s ile ifade ettiğimiz boş karelere genişlet .

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

Girişi /s ile birleştirilen 8 geçerli 8 kareden oluşan 8 setle eşleşmezse silin . ( /Kontrolü kolaylaştırmak için ekstra bir önek eklenmiştir .)

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

Beyaz veya siyah şah yoksa veya ikisinden biri varsa girişi silin.

{2`N

2`B

2`R

1`Q

K

Hala oradalarsa beyazın başlangıç ​​parçalarını silin.

T`L`P

Kalan beyaz parçaları piyonlara indirin.

8`P

Geçerli beyaz piyonları silin.

A`P

Kalan beyaz piyon varsa girişi silin.

}T`l`L

Tekrar kontrol edin, ancak siyah parçalarla.

^.

Satır silinmedikçe doğruluk değeri verin.


6

JavaScript (ES6), 168 174 ... 155

Bu yanıt utanç verici sayıda kez düzenlendi. Umarım, mevcut sürüm hem güvenilir hem de terbiyeli golf.


Bir boole döndürür.

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)

Biçimlendirilmiş ve yorumlanmış

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?

Test senaryoları


3

Python 3, 2842592362524247234 bayt

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)

Çevrimiçi deneyin!

Tüm test senaryoları ile çevrimiçi deneyin!

Bay Xcoder sayesinde -11 bayt

Jonathan Allen sayesinde -13 bayt

+22 Kralların varlığını unuttum.

Bazı açıklamalarla yarı-soluksuz:

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 bayt . Ben yerini ,p,P=9,9ile ;P=p=9.
Bay Xcoder

1
230 bayt . Neden şu alanlarda gereksiz alanlara for-loop
sahiptiniz

1
225 byte : Sen kullanabilirsiniz p>0<Pyerine p>0and P>0çok 5 bayt kaydedin. Alternatif olarak, p and P(-3 bayt için) kullanmış olabilirsiniz, buna ihtiyacınız yoktur >0, çünkü sıfır olmayan değerler Python'da doğrudur
Bay

1
Piyonlar yükseltilebilir, spesifikasyonda 7 küçük piyon ve 4 kale olduğunu söylerken, gözlerim sadece 6 küçük p 'görüyor.
pizzapants184

1
Döngüden o=0önce ile başlatarak ve o+=o<2döngü gövdesinin sonunda ile artırarak 13 bayt kaydedebilirsiniz .
Jonathan Allan

2

PHP , 269 bayt

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

Çevrimiçi deneyin!


2

JavaScript (ES6), 181 172 174 bayt

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 bayt

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

Çevrimiçi deneyin!

En küçük Python sunumu değil, ama yine de bazı vaatleri olduğunu düşünüyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.