Schachendspiel: Weiß, um in einem zu verbinden

19

Wenn Sie ein 8x8-Buchstabenraster haben, das den aktuellen Stand einer Schachpartie darstellt, besteht Ihre Aufgabe darin, einen nächsten Zug für Weiß zu finden, der zu einem Schachmatt führt (die Antwort wird immer ein Zug sein).

Eingang

Die Eingabe erfolgt in STDIN - 8 Zeilen mit jeweils 8 Zeichen. Die Bedeutungen der einzelnen Zeichen sind wie folgt:

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

Großbuchstaben stehen für weiße Teile und Kleinbuchstaben für Schwarz. Das Brett wird so ausgerichtet, dass Weiß von unten nach oben und Schwarz von oben nach unten spielt.

Ausgabe

Ein Zug für Weiß, der zu Schachmatt führt, in algebraischer Notation . Sie müssen weder notieren, wann ein Teil genommen wurde, noch müssen Sie sich Gedanken darüber machen, zwischen zwei identischen Teilen zu unterscheiden, die denselben Zug ausführen können.

Probeneingabe

Beispiel 1

Eingang:

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

Ausgabe:

c6

Beispiel 2

Eingang:

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

Ausgabe:

Nf5

Beispiel 3

Eingang:

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

Ausgabe:

Rh5

Sie können davon ausgehen, dass die Lösung nicht mit Rochade oder En-Passant einhergeht.

Das ist Code-Golf - die kürzeste Lösung gewinnt.

(Beispiele aus mateinone.com - Rätsel 81, 82 und 83)

Gareth
quelle
Nein. Ich denke, für die Zwecke dieser Frage können Sie davon ausgehen, dass die Antwort keine Rochade oder Eignung beinhaltet. Ich werde die Frage aktualisieren.
Gareth
Wie sollen wir mit Positionen mit mehr als einem Partner umgehen?
Rob
@Rob Es ist nur eine Lösung erforderlich. Geben Sie die zuerst gefundene Lösung aus.
Gareth
Ist es auch sicher anzunehmen, dass die Lösung keine Werbung beinhaltet?
Peter Taylor
@Peter Ja, ich möchte das Problem nicht überkomplizieren.
Gareth

Antworten:

7

Ruby, 589 512 510 499 493 Zeichen

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]+/]}

Die Eingabe erfolgt über stdin, zB:

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

Die Ausgabe ist nicht nur eine Bewegung, die einen Partner zwingt, sondern jede Bewegung, die dies tut.

Edit 1: Die Funktion ewurde nur einmal verwendet, also habe ich sie eingefügt. Zweitens basiert die Codierung jetzt auf Nummer 5 statt auf 10. Durch das Refactoring des Boards konnten einige Zeichen eingespart werden.

Edit 2: Immer noch nicht so viel Verbesserung wie ich wollte. Ändern des Hash von {a=>b,c=>d}nach Hash[a,b,c,d]. Dies kostet 4 Zeichen, spart jedoch eines pro Schlüssel-Wert-Paar.

Edit 3: Nur geringfügige Verkleinerungen: Inlining M (4 Zeichen), t==?--> t<?.(2), Entfernen von Pawn in algebraischer Notation am Ende (2), Ersetzte Puts (3). Das Programm hat jetzt weniger als 500 Zeichen.

Edit 4: Es ist interessant, wie viel man noch in einem solchen Programm finden kann. Eine Invariante außerhalb der Schleife verschoben und eine weitere doppelte Berechnung gefunden.

Howard
quelle
Mit "nicht einer, sondern einer" meinen Sie "nicht unbedingt einen, sondern jeden"?
Matthew Read
@Matthew Du hast recht. Ich meinte "jeder".
Howard
Sie können [*$<]anstelle von verwenden $<.map{|l|l}.
Lowjacker