Captura en el tablero de ajedrez

17

Debe escribir un programa o función que reciba una cadena que represente un tablero de ajedrez con solo peones como entrada y salida o devuelva si es posible alguna captura en el tablero.

La entrada está en una notación similar a FEN que describe las posiciones de los peones blancos y negros sin otras piezas presentes. Debes decidir si hay un peón que pueda capturar a un enemigo.

Cada rango se describe, comenzando con el rango 8 y terminando con el rango 1; dentro de cada rango, el contenido de cada cuadro se describe desde el archivo "a" hasta el archivo "h". Cada peón se identifica con una sola letra (peón blanco = "P", peón negro = "p",). Los cuadrados vacíos se observan utilizando los dígitos del 1 al 8 (el número de cuadrados vacíos), y "/" separa los rangos. (parcialmente tomado de Wikipedia)

Por ejemplo

8/pppppppp/8/8/4P3/8/PPPP1PPP/8

describe el tablero

--------

pppppppp


    P   

PPPP PPP

--------

Un peón blanco puede capturar uno negro si el negro se coloca diagonalmente hacia arriba (el negro está arriba a la izquierda o arriba a la derecha) y un peón negro puede capturar uno blanco si el blanco está diagonalmente debajo de él (el blanco es abajo-izquierda o abajo-derecha). Ningún otro movimiento de captura ( en passant ) debe ser considerado.

Entrada

  • Una cadena tipo FEN que consta de los caracteres 12345678pP/.
  • La entrada describe los peones de una posición de juego de ajedrez válida. Esto significa (entre otras restricciones más complejas) habrá como máximo 8 peones para cada lado y no hay peones en los rangos 1 y 8.

Salida

  • Si hay una posible captura para cualquiera de los lados, debe generar un valor verdadero y un valor falso de lo contrario.

Ejemplos

Entradas con salida veraz (una por línea)

8/7p/6P1/8/8/8/8/8
8/8/p7/1P6/3P3p/8/8/8
8/2P5/8/4P1p1/2p2P2/3p4/3p1P2/8
8/P7/8/5P2/2pp4/3P2p1/3pP3/8
8/P7/p7/p1P1P3/1P3p2/8/1p6/8
8/4p1P1/2P2P1P/2p1pPpp/8/6P1/pP1p4/8

Entradas con salida falsa (una por línea)

8/8/8/8/8/8/8/8
8/7P/6p1/8/8/8/8/8
8/7p/7P/8/8/8/8/8
8/pppppppp/8/8/8/8/PPPPPPPP/8
8/p7/8/1p6/5P2/8/8/8
8/p7/P7/2P1p1p1/2p5/8/PP6/8

Este es el código de golf, por lo que gana la entrada más corta.

randomra
fuente
¿No debería ser descrito el tablero de ejemplo 8/pppppppp/8/8/8/7P/PPPP1PPP/8?
TheNumberOne
@TheNumberOne No, 7Psignificaría que el peón está en el último octavo archivo. (Sin embargo, el diagrama era incorrecto, lo corregí.)
randomra
1
Siento que eliminar en passant hace que este sea un rompecabezas menos interesante.
corsiKa

Respuestas:

6

Pyth, 25 bytes

/smC,>JsXz`M9*LN9dJ,8T"Pp

Banco de pruebas

Pasos:

Transforme la entrada reemplazando los dígitos con el número equivalente de comillas ( N). Esto se guarda en J. Luego cortamos los primeros 8 o 10 caracteres y comprimimos el resultado con el original. Cualquier par de captura se transformará en "Pp", por lo que luego encontramos el recuento de esa cadena en la lista resultante. Esta es la salida.

Como beneficio adicional, esto realmente cuenta el número de capturas posibles en la entrada.

isaacg
fuente
Otra solución 25: :sXz`M9*LN9"p.{7}(..)?P"1Lamentablemente, el último parámetro de :no es opcional (creo que debería serlo).
Jakube
3
@Jakube lo hará.
isaacg
12

Retina , 33 29 bytes

T`d`w
)`\d
$0.
_

p.{7}(..)?P

Para ejecutar el código desde un solo archivo, use la -sbandera.

Debe ser fácilmente superable por algo como Perl, donde la expansión de dígitos en cadenas de espacios (u otros caracteres) no ocupa 17 bytes.

El resultado es positivo (verdadero) si hay una captura posible y cero (falso) si no lo hay.

Explicación

T`d`w
)`\d
$0.

Este es un ciclo de dos etapas. La primera es una etapa de transliteración que disminuye cada dígito y convierte los ceros en guiones bajos. ¿Por qué? Porque dy wexpandir a las siguientes dos líneas:

0123456789
_0123456789AB...YZab...yz

Si el conjunto objetivo de una etapa de transliteración es más largo que el conjunto fuente, se ignoran los caracteres extraños, de ahí el comportamiento decreciente (sinceramente, fue una suerte que decidiera poner el guión bajo delante de los dígitos al expandir la wclase de caracteres) .

Luego, la segunda etapa es un reemplazo, que agrega un .a cada dígito. Eso significa que para cada dígito n, nse agregan puntos antes de que ese dígito se convierta en un guión bajo.

_
<empty>

Esto simplemente elimina los guiones bajos.

p.{7}(..)?P

Finalmente, encontramos los partidos. Dado que estamos ignorando en passant, las capturas solo son posibles si hay una py luego una Pdiagonal debajo de ella. En la cadena lineal, esto simplemente significa que debe haber 7 o 9 caracteres entre los dos peones. Esto coincidió con .{7}(..)?(es decir, emparejar 7 caracteres y luego, opcionalmente, emparejar otros dos).

Tal etapa de coincidencia devuelve el número de coincidencias que encontró.

Martin Ender
fuente
Re "Debería ser fácilmente superable por algo como Perl donde la expansión de los dígitos en cadenas de espacios (u otros caracteres) no ocupa 17 bytes": No puedo hacer que Perl iguale tu puntaje, y mucho menos superarlo . ( Mi respuesta de Perl. ) Pero tal vez alguien más pueda ...
msh210
3

Javascript, 272 caracteres

function h(t){b=[[]];for(i=-1;i++<7;){c=0;b.push(l=[]);for(j=-1;j++<7;){o=t.split('/')[i][j];switch(o){case'P':l[c++]=-1;break;case'p':l[c++]=1;break;default:c+=parseInt(o);}}}b.push([]);for(i=1;i<9;i++)for(j=0;j<8;j++)if((p=b[i][j])&&(b[i+p][j-1]||b[i+p][j+1]))return 1;}

Probablemente haya mucho margen de mejora.

Najkin
fuente
3

Ruby, 145 123 46 bytes

->b{b.gsub(/\d/){|x|?.*x.to_i}=~/p.{7}(..)?P/}

No sé por qué no pensé en esto en primer lugar. Es mucho más corto y también bastante legible.

Aquí está la prueba: http://ideone.com/Gzav8N


El viejo enfoque:

->b{l={}
r=p
b.split(?/).map{|s|c={}
i=0
s.chars.map{|x|n=x.to_i;c[i]=x;i+=n<1?1:n;x==?P&&r||=l[i-2]==?p||l[i]==?p}
l=c}
r}

Prueba en línea: http://ideone.com/9L01lf , versión antes del golf: http://ideone.com/CSmqlW

Un historial de modificaciones está disponible aquí .

Cristian Lupascu
fuente
2

ES6, 64 bytes

¡Un recuento de bytes apropiado, si dura!

f=s=>/p.{7}(..)?P/.test(s.replace(/\d/g,n=>"        ".slice(-n)))

De hecho, pensé en esta solución sin leer las otras respuestas primero, pero no me importará si no me crees.

Neil
fuente
0

PHP, 94 87 80 bytes

for(;$i++<8;)$t[$i]=$s.=" ";echo preg_match("#p.{7}(..)?P#",strtr($argv[1],$t));

Ese bucle + strtres mucho más corto que preg_replace_callbackcon str_pad.

Tito
fuente
0

Gelatina, 88 84 79 72 69 65 64 63 60 bytes

Definitivamente margen de mejora. Sin competencia porque Jelly se creó antes de la pregunta. ¡Gracias a @lirtosiast por decirme eso!

ØDṖḊ
”_x
e1£¬
1£iЀ2Ŀ€
x"3Ŀ€;"ÇFṣ”/
w€⁾pPn0
5ĿUŒDÇ
5ĿŒD6ĿoÇS
Zacharý
fuente