Fin de partie d'échecs: White to Mate In One


19

Étant donné une grille de lettres 8x8 représentant l'état actuel d'une partie d'échecs, la tâche de votre programme est de trouver un prochain coup pour les blancs qui se traduit par échec et mat (la réponse sera toujours mate en un coup).

Contribution

L'entrée se fera sur STDIN - 8 lignes de 8 caractères chacune. Les significations de chaque caractère sont les suivantes:

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

Les lettres majuscules représentent des morceaux blancs et les minuscules représentent le noir. Le plateau sera orienté de façon à ce que le blanc joue vers le haut et le noir vers le bas.

Production

Un coup pour le blanc qui se traduit par échec et mat, en notation algébrique . Vous n'avez pas besoin de noter quand une pièce a été prise, ni de vous soucier de lever l'ambiguïté entre deux pièces identiques qui peuvent faire le même mouvement.

Exemple d'entrée

Exemple 1

Contribution:

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

Production:

c6

Exemple 2

Contribution:

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

Production:

Nf5

Exemple 3

Contribution:

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

Production:

Rh5

Vous pouvez supposer que la solution n'impliquera pas de roque ou en passant.

C'est le code-golf - la solution la plus courte l'emporte.

(Exemples tirés de mateinone.com - puzzles 81, 82 et 83)


Non. Je pense qu'aux fins de cette question, vous pouvez supposer que la réponse n'impliquera pas de roque ou de passage. Je mettrai à jour la question.
Gareth

Comment devrions-nous gérer les positions avec plus d'un compagnon en un?
Rob

@Rob Une seule solution est requise, donc sortez la solution que vous trouvez en premier.
Gareth

Est-il également sûr de supposer que la solution n'implique pas de promotion?
Peter Taylor

@Peter Oui, je ne veux pas trop compliquer le problème.
Gareth

Réponses:


7

Ruby, 589 512 510 499 493 caractères

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

L'entrée est donnée via stdin, par exemple:

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

La sortie n'est pas seulement un coup qui force un compagnon en un, mais chaque coup qui le fait.

Edit 1: La fonction en'a été utilisée qu'une seule fois, je l'ai donc insérée. Deuxièmement, l'encodage est maintenant basé sur le numéro 5 au lieu de 10. Et la refactorisation du clonage de la carte a sauvé pas mal de caractères.

Edit 2: Toujours pas autant d'améliorations que je voulais. Changer le hachage de {a=>b,c=>d}à Hash[a,b,c,d]. Cela coûte 4 caractères mais enregistre un par paire clé-valeur.

Edit 3: Seulement des réductions mineures: inline M (4 caractères), t==?--> t<?.(2), suppression du pion en notation algébrique à la fin (2), remplacements put (3). Le programme compte désormais moins de 500 caractères.

Edit 4: Il est intéressant de voir combien on peut encore trouver dans un tel programme. Déplacé un invariant hors de la boucle et trouvé un autre calcul en double.


Par «pas un, mais n'importe lequel», voulez-vous dire «pas nécessairement un, mais tous»?
Matthew Read

@Matthew Tu as raison. Je voulais dire "tous".
Howard

Vous pouvez utiliser à la [*$<]place de $<.map{|l|l}.
Lowjacker
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.