Końcowa gra w szachy: biała do Mate In One


19

Biorąc pod uwagę siatkę 8x8 liter reprezentujących aktualny stan gry w szachy, Twoim programem jest znalezienie następnego ruchu dla białych, który skutkuje matą (odpowiedź zawsze będzie wiązana w jednym ruchu).

Wejście

Dane wejściowe będą na STDIN - 8 linii po 8 znaków każdy. Znaczenie każdego znaku jest następujące:

K/k - king
Q/q - queen
B/b - bishop
N/n - knight
R/r - rook
P/p - pawn
- - empty square

Wielkie litery oznaczają białe elementy, a małe - czarny. Plansza zostanie ustawiona w taki sposób, że biel będzie odgrywać od dołu, a czerń od góry.

Wynik

Ruch dla bieli, który powoduje mat, w zapisie algebraicznym . Nie musisz notować, kiedy kawałek został zabrany, ani nie musisz się martwić rozróżnieniem dwóch identycznych elementów, które mogą wykonać ten sam ruch.

Przykładowe dane wejściowe

Przykład 1

Wejście:

------R-
--p-kp-p
-----n--
--PPK---
p----P-r
B-------
--------
--------

Wynik:

c6

Przykład 2

Wejście:

--b-r--r
ppq-kp-p
-np-pn-B
--------
---N----
--P----P
PP---PP-
R--QRBK-

Wynik:

Nf5

Przykład 3

Wejście:

---r-nr-
-pqb-p-k
pn--p-p-
R-------
--------
-P-B-N-P
-BP--PP-
---QR-K-

Wynik:

Rh5

Możesz założyć, że rozwiązanie nie będzie wiązało się z kastracją ani en-pasywacją.

To jest golf golfowy - wygrywa najkrótsze rozwiązanie.

(Przykłady zaczerpnięte z mateinone.com - puzzle 81, 82 i 83)


Nie. Myślę, że do celów tego pytania można założyć, że odpowiedź nie będzie obejmować racji ani en-passant. Zaktualizuję pytanie.
Gareth

Jak powinniśmy radzić sobie z pozycjami z więcej niż jednym partnerem w jednym?
Rob

@Rob Wymagane jest tylko jedno rozwiązanie, więc wypisz dowolne rozwiązanie, które znajdziesz jako pierwsze.
Gareth

Czy można również bezpiecznie założyć, że rozwiązanie nie obejmuje promocji?
Peter Taylor

@ Peter Tak, nie chcę nadmiernie komplikować problemu.
Gareth

Odpowiedzi:


7

Rubinowy, 589 512 510 499 493 znaków

R=0..7
a=->b{o=[];R.map{|r|R.map{|c|v=Hash[?K,[6,7,8,11,13,16,17,18],?R,s=[157,161,163,167],?B,t=[156,158,166,168],?Q,s+t,?N,[1,3,5,9,15,19,21,23],?P,[32,181,183]][z=b[r][c]];v&&v.map{|s|k=2!=l=s/25+1;u=r;v=c;l.times{u+=s/5%5-2;v+=s%5-2;R===u&&R===v||break;t=b[u][v];j=t<?.&&l<8;(j||t=~/[a-z]/&&k)&&o<<=(h=b.map &:swapcase;h[u][v]=h[r][c];h[r][c]=?-;[z+"%c%d"%[97+v,8-u],h.reverse]);j&&(k||r==6)||break}}}};o}
a[$<.map{|l|l}].map{|m,b|a[b].any?{|f,x|a[x].all?{|g,y|y*""=~/K/}}||$><<m[/[^P]+/]}

Dane wejściowe są podawane przez stdin, np .:

> ruby mateinone.rb
--------
--------
--------
-k------
b-------
-N-P----
--------
-----K-Q
^Z
Qb7

Wyjście to nie tylko jeden ruch, który zmusza partnera w jednym, ale każdy ruch, który to robi.

Edycja 1: Funkcja ezostała użyta tylko raz, więc ją wstawiłem. Po drugie, kodowanie opiera się teraz na liczbie 5 zamiast 10. A refaktoryzacja klonowania płytki pozwoliła zaoszczędzić sporo znaków.

Edycja 2: Nadal nie tak wiele ulepszeń, jak chciałem. Zmiana skrótu z {a=>b,c=>d}na Hash[a,b,c,d]. Kosztuje to 4 znaki, ale oszczędza jeden na parę klucz-wartość.

Edycja 3: Tylko drobne redukcje: wstawianie M (4 znaki), t==?--> t<?.(2), usuwanie pionka w notacji algebraicznej na końcu (2), zamiana puts (3). Program ma teraz mniej niż 500 znaków.

Edycja 4: Ciekawe, ile jeszcze można znaleźć w takim programie. Przeniesiono niezmiennik poza pętlę i znalazłem kolejne zdublowane obliczenie.


Przez „nie jeden, ale każdy” masz na myśli „niekoniecznie jeden, ale każdy”?
Mateusz

@Matthew Masz rację. Miałem na myśli „każdy”.
Howard

Możesz użyć [*$<]zamiast $<.map{|l|l}.
Lowjacker
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.