Juego final de ajedrez: blanco para aparearse en uno

19

Dada una cuadrícula de letras de 8x8 que representa el estado actual de un juego de ajedrez, la tarea de su programa es encontrar un próximo movimiento para las blancas que resulte en jaque mate (la respuesta siempre será compañero en un movimiento).

Entrada

La entrada estará en STDIN: 8 líneas de 8 caracteres cada una. Los significados de cada personaje son los siguientes:

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

Las letras mayúsculas representan piezas blancas y las minúsculas representan negro. El tablero estará orientado de modo que el blanco se juegue desde abajo y el negro desde arriba.

Salida

Un movimiento para el blanco que resulta en jaque mate, en notación algebraica . No necesita anotar cuándo se ha tomado una pieza, ni debe preocuparse por la desambiguación entre dos piezas idénticas que pueden hacer el mismo movimiento.

Entrada de muestra

Ejemplo 1

Entrada:

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

Salida:

c6

Ejemplo 2

Entrada:

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

Salida:

Nf5

Ejemplo 3

Entrada:

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

Salida:

Rh5

Puede suponer que la solución no implicará enroque o pasajero.

Este es el código de golf: la solución más corta gana.

(Ejemplos tomados de mateinone.com - rompecabezas 81, 82 y 83)

Gareth
fuente
No. Creo que, a los efectos de esta pregunta, puede suponer que la respuesta no implicará enroque o pasajero. Actualizaré la pregunta.
Gareth
¿Cómo debemos manejar las posiciones con más de un compañero en uno?
Rob
@Rob Solo se requiere una solución, por lo tanto, imprima la solución que encuentre primero.
Gareth
¿También es seguro asumir que la solución no implica promoción?
Peter Taylor
@ Peter Sí, no quiero complicar demasiado el problema.
Gareth el

Respuestas:

7

Ruby, 589 512 510 499 493 caracteres

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

La entrada se proporciona a través de stdin, por ejemplo:

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

La salida no es solo un movimiento que fuerza a un compañero en uno, sino cada movimiento que lo hace.

Edición 1: la función ese usó solo una vez, así que la alineé. En segundo lugar, la codificación ahora se basa en el número 5 en lugar de 10. Y refactorizar la clonación del tablero ahorró bastantes caracteres.

Edición 2: Todavía no hay tanta mejora como quería. Cambiar el hash de {a=>b,c=>d}a Hash[a,b,c,d]. Esto cuesta 4 caracteres pero ahorra uno por par clave-valor.

Edición 3: Solo reducciones menores: alineando M (4 caracteres), t==?--> t<?.(2), eliminando Peón en notación algebraica al final (2), reemplaza put (3). El programa ahora tiene menos de 500 caracteres.

Edición 4: es interesante cuánto se puede encontrar en un programa de este tipo. Movió un invariante fuera del ciclo y encontró otro cálculo duplicado.

Howard
fuente
Por "no uno, sino cualquiera", ¿quiere decir "no necesariamente uno, sino todos"?
Mateo leyó el
@Matthew Tienes razón. Quise decir "todos".
Howard
Puedes usar en [*$<]lugar de $<.map{|l|l}.
Lowjacker