Dime los movimientos


28

Jack y Jane decidieron jugar una partida de ajedrez para pasar el tiempo. Desafortunadamente, Jack es bastante malo visualizando. ¡Le resulta difícil imaginar los movimientos posibles para una pieza determinada que no sea un peón, por supuesto!

Su desafío es ayudar a encontrar a Jack las posibles opciones para una pieza determinada (que no sea un peón).

En caso de que uno haya olvidado, las diversas piezas se denotan por:

  • K: rey
  • Q: reina
  • N: caballero
  • B: obispo
  • R: torre

Como ejemplo, en la siguiente imagen la Knight se encuentra en d4y se puede mover a c2, b3, b5, c6, e6, f5, f3, e2. Para una entrada dada:

Nd4

usted produciría:

Nc2 Nb3 Nb5 Nc6 Ne6 Nf5 Nf3 Ne2

ingrese la descripción de la imagen aquí

Reglas:

  • El orden de la salida no importa siempre que se enumeren todos los movimientos posibles
  • Los movimientos posibles se pueden separar por espacios en blanco, líneas nuevas o cualquier otro delimitador
  • La entrada se puede pasar al programa como parámetro o mediante STDIN
  • Se contarán los espacios en blanco en el programa, por lo tanto, haga un uso óptimo del mismo.

Este es el código de golf. (Por favor, evite utilizar herramientas / utilidades específicamente diseñadas para este propósito). ¡La respuesta más corta gana!


1
Creo que esto funcionaría bien como un código de golf
John Dvorak

3
El golf de código es la mejor opción. Lo obvio siempre se olvida: entiendo que podemos enviar una función o un programa, y ​​que la entrada / salida puede ser stdin / stout o parámetros / valor de retorno. Estoy pensando que la recursión podría ser útil aquí para la reina: f(x)... case "Q": {f("B");f("R")}si la función requiere algún #incluye, estos deberían ser parte del recuento de bytes.
Level River St

44
La fuente en ese gráfico. xD
cjfaure

1
¿Los movimientos posibles tienen que estar separados por espacios o las líneas nuevas también están bien?
Dennis

1
Los movimientos legales para un peón son más intrincados que cualquier otra pieza (pasante, captura diagonal y el movimiento inicial de 2 casillas). ¿así que supongo que Jack también tiene memorizadas las reglas de enroque?
ardnew

Respuestas:


7

GolfScript, 94 93 caracteres

¡Mi primer programa GolfScript! Esto me llevó muchas horas buscando sin saber lo que estaba haciendo, pero insistí y creo que logré aprender los conceptos básicos del idioma y jugar golf bastante bien.

Completamente golfizado :

{}/8,{97+.3$-.*:>8,{49+.4$-.*:^2$+.[3<>^*4=>^=>^*!.2$|]"KNBRQ"8$?=*{[5$3$@]""+p}{;}if}/;;}/];

Fuente comentada y más agradable :

{}/              # tIn fIn rIn
8,{97+           #             fTst
  .3$-.*:>       #                  fDif^2 : >
  8,{49+         #                         rTst 
    .4$-.*:^     #                              rDif^2 : ^
    2$+.         #                                     ^>+
    [3<          # These    #                              [validK
     >^*4=       # checks   #                                      validN
     >^=         # do not   #                                             validB
     >^*!        # account  #                                                    validR
     .2$|]       # for null #                                                           validQ]
    "KNBRQ"8$?=  # move;    #                          valid
    *            # * does.  #                          validNotNull
    {[5$3$@]""+p}{;}if  # print? #  fDif^2
  }/;;           #        rIn
}/];

Puede parecer la respuesta de Claudiu, que es porque hice referencia a su respuesta, así como a mi solución C (no presentada), mientras hacía la mía. Proporcionó una buena muestra de un programa de GolfScript (relativamente) complejo y funcional, y me ayudó a aprender mucho sobre el lenguaje. ¡Gracias, Claudiu!

Siendo nuevo en GolfScript todavía, si ustedes tienen algún comentario, les agradecería escucharlo.


¡Increíble! Buen trabajo =). Tendré que verlo más de cerca más adelante para ver cómo obtuviste 40 caracteres más cortos que el mío. ¿No es divertido Golfscript?
Claudiu

12

Python, 217 212 220 217 213 caracteres

Atado la solución de Mathematica de 213 bytes

R=range(8)
def f((p,x,y)):
 for a in R:
    for b in R:
     A,B=abs(a-ord(x)+97),abs(b-ord(y)+49);C=max(A,B);r=(A+B==3and C<3,C<2,A*B<1,A==B,0)
     if(r['NKRBQ'.index(p)],any(r[1:]))[p=='Q']*C:print p+chr(a+97)+chr(b+49)

Comencé generando todos los movimientos válidos, pero eso creció demasiado, por lo que el enfoque es bastante similar al de Mathematica.

>>> f("Nd4")
Nb3
Nb5
Nc2
Nc6
Ne2
Ne6
Nf3
Nf5
>>> f("Qa1")
Qa2
Qa3
Qa4
Qa5
Qa6
Qa7
Qa8
Qb1
Qb2
Qc1
Qc3
Qd1
Qd4
Qe1
Qe5
Qf1
Qf6
Qg1
Qg7
Qh1
Qh8

Extracción agradable de caracteres de cadena con esta tupla de argumento. Lástima que ya no funcione en Python 3.
Evpok

10

Mathematica, 278 272 264 260 215 213 caracteres

f=(FromCharacterCode@Flatten[Table[c=Abs[#2-x];d=Abs[#3-y];b=c==d;r=#2==x||#3==y;If[Switch[#-75,0,c~Max~d<2,-9,b,7,r,6,b||r,3,!r&&c+d==3],{p,x,y},##&[]],{x,97,104},{y,49,56}]&@@ToCharacterCode@#,1]~DeleteCases~#)&

Versión sin golf:

f[pos_] := (
  {piece, u, v} = ToCharacterCode@pos;
  board = Flatten[Table[{piece, i + 96, j + 48}, {i, 8}, {j, 8}], 1];
  DeleteCases[
    FromCharacterCode[
      Cases[board, {_, x_, y_} /; Switch[p,
        75, (* K *)
        ChessboardDistance[{x, y}, {u, v}] < 2,
        66, (* B *)
        Abs[u - x] == Abs[v - y],
        82, (* R *)
        u == x || v == y,
        81, (* Q *)
        Abs[u - x] == Abs[v - y] || u == x || v == y,
        78, (* N *)
        u != x && v != y && ManhattanDistance[{x, y}, {u, v}] == 3
        ]
      ]
    ], 
    pos (* remove the input position *)
  ]
)&

Ejemplo de uso:

f["Nd4"]
> {"Nb3", "Nb5", "Nc2", "Nc6", "Ne2", "Ne6", "Nf3", "Nf5"}

La versión sin golf crea un tablero completo, y luego selecciona las posiciones correctas Cases, mientras que la versión con golf elimina movimientos inválidos inmediatamente en el Tablecomando mediante la emisión ##&[], que simplemente desaparece.


Solo curiosidad por la entrada, ¿no N4d? ¿No debería ser Nd4en su lugar?
devnull

@devnull seguro, eso es un error tipográfico. debería ser Nd4.
Martin Ender

Aprendí una función conocida hoyChessboardDistance
swish

Según la documentación de Mathematica / Wolfram Language, "ChessboardDistance [u, v] es equivalente a Max [Abs [uv]]". Quizás pueda guardar caracteres usando la última forma, especialmente si reemplaza Abs [uv] con | uv |.
Michael Stern el

@MichaelStern eso es exactamente lo que estoy haciendo en la versión de golf;). Y desafortunadamente, las barras verticales no funcionan Absen Mathematica, porque denotan alternativas en un patrón.
Martin Ender

10

Haskell 225 220 208 205 200 182

f=fromEnum
m[p,a,b]=[[p,c,r]|c<-"abcdefgh",r<-"12345678",let{s=abs$f a-f c;t=abs$f b-f r;g"K"=s<2&&t<2;g"Q"=g"B"||g"R";g"N"=s+t==3&&(s-t)^2<2;g"B"=s==t;g"R"=s<1||t<1}in s+t>0&&g[p]]

Va a ser difícil tocar Mathematica cuando eso tiene movimientos de ajedrez incorporados: rollseyes: (bien jugado m.buettner) Lo recupero todo. ¡Venciendo a Mathematica por 31!

Última edición: caso reemplazado con una función, filtro integrado en la comprensión, para superar la entrada en R;)

uso:

ghci> m "Nd4"
["Nb3","Nb5","Nc2","Nc6","Ne2","Ne6","Nf3","Nf5"]

Ungolfed (corresponde a la versión 208 char antes de que 'u' estuviera en línea):

f=fromEnum -- fromEnum is 'ord' but for all enum types,
           -- and it's in the prelude, so you don't need an extra import.
u piece dx dy= -- piece is the character eg 'K', dx/dy are absolute so >=0.
  dx+dy > 0 && -- the piece must move.
  case piece of
    'K'->dx<2&&dy<2         -- '<2' works because we already checked dx+dy>0
    'Q'->dx<1||dy<1||dx==dy -- rook or bishop move. see below.
    'N'->dx+dy == 3 &&      -- either 2+1 or 3+0. Exclude the other...
         (dx-dy)^2 < 2      -- 1^2 or 3^2, so valid move is '<2', ie '==1'
    'B'->dx==dy             -- if dx==dy, dx/=0 - we checked that. 
                            -- other moves with dx==dy are along diagonal
    _->dx<1||dy<1           -- use _ not 'R' to save space, default case is
                            -- the rook. '<1' saves chars over '==0'.
                            -- Again, dx==dy==0 edge case is excluded.
m[piece,file,rank]=       -- the move for a piece. 'parse' by pattern match.
 filter(                    -- filter...
  \[_,newfile,newrank]->    -- ...each possible move...
    u piece                 -- ...by, as everyone noticed, converting char..
      (abs$f file-f newfile) -- differences to absolute dx, dy differences,..
      (abs$f rank-f newrank)) -- and then using special routines per piece.
    [[piece,newfile, newrank] -- the output format requires these 3 things.
      |newfile<-"abcdefgh",newrank<-"12345678"] -- and this just generates moves.

¿Puedes publicar una versión sin golf también? (si tiene uno, por supuesto)
swish

@swish no, pero no me importa escribir eso.
bazzargh

@swish hecho. Espero que eso tenga más sentido. Pregunta si necesitas algo aclarado.
bazzargh

¡Gran trabajo! ¿Por qué necesita agregar piecea la lista [piece,newfile, newrank]si no lo usa en la coincidencia de patrones, puede guardar algunos caracteres?
swish

Está ahí para la salida. Verás que no coincido con el patrón en '... cada movimiento posible ...'. Originalmente no tenía esto, los movimientos de ajedrez no lo requieren, pero luego me di cuenta de que la pregunta lo quería, y todos los demás lo hicieron, por lo que es justo.
bazzargh

8

Bash, 238

B={19..133..19}\ {21..147..21};K=1\ {19..21};N='18 22 39 41';R={1..7}\ {2..14..2}0;Q=$B\ $R
a=${1%??};b=$[20#${1:1}-200];c=`eval{,} echo '$'$a`;d=({a..h})
for i in $c -${c// / -};do echo $a${d[$[(i+=b)/20]]}$[i%20];done|grep '[a-h][1-8]$'

Cómo funciona

  • La idea es representar cada campo en el tablero por un valor numérico, tomando sus coordenadas como un número base 20 y restando 200. De esta manera, se a1convierte 20 * 10 + 1 - 200 = 1, se h8convierte 20 * 17 + 8 - 200 = 148, etc.

    Ahora, los posibles movimientos del Obispo se pueden representar mediante múltiplos (positivos o negativos) de 19 - la misma cantidad de pasos hacia arriba (+20) y hacia la izquierda (-1) - o 21 - la misma cantidad de pasos hacia arriba (+20 ) y a la derecha (+1).

    La colocación de la figura después del movimiento es simplemente la suma de su posición original y el movimiento. Después de sumar esos números, tenemos que verificar si su suma corresponde a un campo válido en el tablero.

    Dado que la base (20) es más del doble del número más alto posible (8), la suma no se puede ajustar alrededor del tablero, por ejemplo, mover Bh1 siete pasos hacia la derecha y hacia arriba dará como resultado una posición de tablero no válida.

  • La línea

    B={19..133..19}\ {21..147..21};K=1\ {19..21};N='18 22 39 41';R={1..7}\ {2..14..2}0;Q=$B\ $R
    

    enumera todos los movimientos posibles de las piezas que están representados por números positivos.

  • Los comandos

    a=${1%??};b=$[20#${1:1}-200];c=`eval{,} echo '$'$a`;d=({a..h})
    

    almacena el identificador de la pieza en la variable a , la representación numérica de la posición original en b y las letras a a h en la matriz d .

    Después de la expansión de la llave, se eval{,} echo '$'$aconvierte eval eval echo '$'$a(doblemente malvado), que se evalúa como, por ejemplo eval echo $K, que se evalúa como echo 1 19 20 21.

  • for i in $c -${c// / -};do …; done recorre todos los movimientos posibles y sus contrapartes negativas.

  • echo $a${d[$[(i+=b)/20]]}$[i%20] da la posición final después del movimiento.

  • grep '[a-h][1-8]$' se asegura de que tengamos una posición válida en el tablero.


7

Golfscript, 144 135 caracteres

En lugar de seguir intentando jugar golf con mi solución Python , la traduje a Golfscript:

{}/49-:y;97-:x;:N;8,{.x-abs:A
8,{.y-abs:B@[\]$1=:C[B
A+3=\3<&2C>B
A*1<B
A=]81N={(;{|}*}{"NKRB"N?=}if
C*{[N
2$97+@49+]''+p}{;}if
A}/;;}/

Traducción directa sin mucho golf, por lo que lo más probable es que pueda reducirse aún más. Toma datos de stdin sin una nueva línea, pruébalo aquí (las primeras dos líneas son para imitar stdin).


Parece funcionar bien! Espero que a alguien se le ocurra una solución brainf * ck también.
devnull

6

C 634 632 629 625 600 caracteres

#define F for(;i<4;i++){
#define B ;}break;
#define O x=X,y=Y,
P,X,Y,c,r,x,y,i=0, N[8][2]={{-2,1},{-1,2},{1,2},{2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}},S[4][2]={{1,0},{0,1},{-1,0},{0,-1}},D[4][2]={{-1,1},{-1,-1},{1,1},{1,-1}};
C(){return((0<=c)&(c<8)&(0<r)&(r<9))?printf("%c%c%d ",P,c+'a',r):0;}
M(int*m){c=m[0]+x,r=m[1]+y;C()?x=c,y=r,M(m):0;}
main(int a,char**v){char*p=v[1];P=*p,X=p[1]-97,Y=p[2]-48; switch(P){case 75:F c=S[i][1]+X,r=S[i][0]+Y,C(),c=D[i][1]+X,r=D[i][0]+Y,C()B case 81:F O M(D[i]),O M(S[i])B case 78:for(;i<8;i++){c=N[i][1]+X,r=N[i][0]+Y,C()B case 66:F O M(D[i])B case 82:F O M(S[i])B}}

¿Alguna sugerencia sobre cómo mejorar esto? Esta es la primera vez que envío una respuesta.


¡Bienvenido a Code Golf! Para empezar, puede eliminar el espacio en blanco en su código. Recuerde que este es el código de golf, lo que implica que gana el código más corto. Intente reducir el tamaño de su programa.
devnull

¡Recuerde actualizar el recuento de caracteres también!
devnull

@devnull ¿se cuentan los espacios necesarios?
calccrypto

1
Una cosa más: Cse puede simplificar enormemente utilizando el operador ternario ?:y utilizando el valor de retorno de printf. ( printfdevuelve el número de caracteres escritos, por lo que en este caso siempre es distinto de cero) C(P,c,r){return(0<=c)&(c<8)&(0<r)&(r<9)?printf("%c%c%d ",P,c+'a',r):0;}. Una edición menor: hay un espacio adicional Mdespués del ifque puedes eliminar.
user12205

1
En este momento, parece que no estás contando ninguna nueva línea. Si bien algunos de ellos se pueden eliminar, otros no. Las nuevas líneas requeridas definitivamente deberían contribuir al recuento de bytes.
Dennis

3

Haskell, 300 269 ​​caracteres

Gracias a bazzargh por ayudarme a perder 31 personajes ...

import Data.Char
f x=filter(x#)[x!!0:y|y<-[v:[w]|v<-"abcdefgh",w<-"12345678"],y/=tail x]
a%b=abs(ord a-ord b)
x#y=let{h=(x!!1)%(y!!1);v=(x!!2)%(y!!2);m=max h v;n=min h v}in case(x!!0)of{'N'->m==2&&n==1;'K'->m==1;'B'->h==v;'R'->n==0;'Q'->('R':tail x)#y||('B':tail x)#y}

Mismo algoritmo que la versión de Mathematica. Salida de muestra de ghci:

*Main> f "Nd4"
["Nb3","Nb5","Nc2","Nc6","Ne2","Ne6","Nf3","Nf5"]
*Main> f "Ni9"
["Ng8","Nh7"]

(¡No solicitaste la comprobación de la cordura!)


Puede deshacerse del espacio en blanco sintáctico. Vea mi respuesta aquí: codegolf.stackexchange.com/questions/19255/… (para ser más específico, desea dejar {h = d (x !! 1) (y !! 1); ...})
bazzargh

1

Haskell, 446 caracteres

import Data.Char
a=[-2,-1,1,2]
b=[-1,1]
d=[1..8]
e=[-8..8]
g=[-1..1]
h 'N' c r=[(c+x,r+y)|x<-a,y<-a,3==(sum$map abs[x, y])]
h 'B' c r=[(c+x*z,r+y*z)|x<-b,y<-b,z<-d]
h 'R' c r=[(c+x,r)|x<-e]++[(c,r+y)|y<-e]
h 'Q' c r=h 'B' c r++h 'R' c r
h 'K' c r=[(c+x,r+y)|x<-g,y<-g]
l s=ord s-96
m n=chr$n+96
k ch (c,r)=ch:m c:[intToDigit r]
f (x,y)=all(`elem`[1..8])[x, y]
i n c r=map(k n).filter(/=(c,r)).filter f$h n c r
j s=i(s!!0)(l$s!!1)(digitToInt$s!!2)

Llamado usando la jfunción

j "Nd4"

No he trabajado con Haskell en unos meses, por lo que no terminó siendo tan breve como la mayoría de las otras soluciones, pero estoy seguro de que hay algunas optimizaciones que hacer, principalmente con h. Podría acortarlo un poco.


1

q & k [ 311 262 caracteres]

Existe la posibilidad de reducir algunos caracteres más. Lo reduciré en la próxima iteración.

k)o:{n:#m:&(#x)##y;((),x)[m],'n#y}

k)a:`$"c"$(o/)c:+(97;49)+/:!8

k)r:{{|x@<x}'?,/{o[x]y}'[x](|"c"$c)}
k)k:{"c"$(6h$x)+/:(o/)2 3#-1 0 1}
k)n:{"c"$(6h$x)+/:(|:'t),t:o[-1 1;2 2]}
k)b:{"c"$(6h$x)+/:(n,'n),n,'|n:-8+!17}
k)q:{,/(r;b)@\:x}

d:{(`$("rknbq"!(r;k;n;b;q))[x]y)except`$y}
g:{a inter d[x 0]@1_x}

Uso

Torre

g"ra1"
`a2`a3`a4`a5`a6`a7`a8`b1`c1`d1`e1`f1`g1`h1

Rey

g"ka1"
`a2`b1`b2

Caballero

g"na1"
`b3`c2

obispo

g"ba1"
`b2`c3`d4`e5`f6`g7`h8

Reina

g"qa1"
`a2`a3`a4`a5`a6`a7`a8`b1`b2`c1`c3`d1`d4`e1`e5`f1`f6`g1`g7`h1`h8

0

R, 203 caracteres

f=function(p,x,y){x=which((l=letters)==x);X=rep(1:8,8);Y=rep(1:8,rep(8,8));A=abs(X-x);L=abs(Y-y);B=A==L;R=!A|!L;i=switch(p,N=A+L==3&A&L,R=R,B=B,Q=R|B,K=(R|B)&A<2&L<2)&A+L>0;paste(p,l[X[i]],Y[i],sep="")}

Versión sin golf:

f = function(p,x,y) {
  x = which(letters == x)  # Gives index between 1 and 8.
  X = rep(1:8, 8)          # 1,2,...,7,8,1,2,.... (8x8).
  Y = rep(1:8, rep(8,8))   # 1,1,...2,2,.....,8,8 (8x8).
  dx = abs(X-x)
  dy = abs(Y-y)
  B = (dx == dy)           # Bishop solutions
  R = (!dx | !dy)          # Rock solutions
  i = switch(p,
             N=dx+dy==3 & dx & dx,  # Sum of dist. is 3, dx and dy must be <> 0.
             R=R, 
             B=B, 
             Q=R|B,                 # Queen is merge of rock and bishop.
             K=(R|B) & dx<2 & dy<2  # King's distance is < 2.
             ) & (dx+dy > 0)        # Exclude start field.

  paste(p, letters[X[i]], Y[i], sep="")
}

Uso:

> f('N', 'a', 3)
[1] "Nb1" "Nc2" "Nc4" "Nb5"

La solución es incluso buena legible. Sin embargo, agregué algunos paréntesis y comentarios para lectores que no están familiarizados con el código R (en la versión sin golf).


0

Haskell (hipotético), 248 caracteres

import Data.Char
f x=filter(o x)[x!!0:y|y<-[v:[w]|v<-"abcdefgh",w<-"12345678"],y/=tail x]
d a b=abs(ord a-ord b)
h x y=(c*(d(x!!1)(y!!1))-(d(x!!2)(y!!2)))+200*c
 where c=d (x!!0)'A'
o x y=elem(chr(h x y))"ਲ਼ੁߏߚߙÈേെ൅ൄൃ൙൪ൻඌඝථ඿౿౾౽౼౻౺౹ಐಏಠಞರಭೀ಼೐ೋೠ೚೰೩"

Desafortunadamente, todos los compiladores de Haskell a los que tengo acceso ahora tienen problemas con los literales de cadena Unicode. Aquí está la versión (más larga) que realmente funciona:

import Data.Char
f x=filter(o x)[x!!0:y|y<-[v:[w]|v<-"abcdefgh",w<-"12345678"],y/=tail x]
d a b=abs(ord a-ord b)
h x y=(c*(d(x!!1)(y!!1))-(d(x!!2)(y!!2)))+200*c
 where c=d (x!!0)'A'
o x y=elem(chr(h x y))"\2611\2625\1999\2010\2009\200\3399\3398\3397\3396\3395\3394\3393\3417\3434\3451\3468\3485\3502\3519\3199\3198\3197\3196\3195\3194\3193\3216\3215\3232\3230\3248\3245\3264\3260\3280\3275\3296\3290\3312\3305"

La definición h x y=...es una función hash; los movimientos válidos se dividirán en números de caracteres que se encuentran en la cadena de 41 caracteres. Esto elimina la necesidad de una declaración de "caso" o equivalente.

No estoy planeando trabajar más en esto ahora. Sería divertido ver si alguien puede usar una función hash en un lenguaje más conciso para hacer una solución más corta.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.