Diga-me os movimentos

28

Jack e Jane decidiram jogar uma partida de xadrez para passar o tempo fora. Infelizmente, Jack é bastante ruim em visualizar. Ele acha difícil imaginar os movimentos possíveis para uma determinada peça que não seja um peão, é claro!

Seu desafio é ajudar a encontrar Jack as opções possíveis para uma determinada peça (exceto um peão).

Caso se tenha esquecido, as várias peças são indicadas por:

  • K: King
  • Q: rainha
  • N: Cavaleiro
  • B: Bispo
  • R: Rook

Como um exemplo, na imagem seguinte o cavaleiro está localizado na d4e pode mover-se para c2, b3, b5, c6, e6, f5, f3, e2. Para uma determinada entrada:

Nd4

você produziria:

Nc2 Nb3 Nb5 Nc6 Ne6 Nf5 Nf3 Ne2

insira a descrição da imagem aqui

Regras:

  • A ordem da saída não importa, desde que todos os movimentos possíveis estejam listados
  • Os movimentos possíveis podem ser separados por espaços em branco, novas linhas ou qualquer outro delimitador
  • A entrada pode ser transmitida ao programa como parâmetro ou via STDIN
  • Os espaços em branco no programa devem ser contados; portanto, faça o melhor uso possível.

Isso é código de golfe. (Evite usar quaisquer ferramentas / utilitários projetados especificamente para essa finalidade.) A resposta mais curta vence!

devnull
fonte
1
Eu acredito que este iria funcionar muito bem como um campo de golfe de código
John Dvorak
3
Código de golfe é a melhor escolha. O óbvio é sempre esquecido: entendo que podemos enviar uma função ou um programa e que entrada / saída pode ser stdin / stout ou parâmetros / valor de retorno. Estou achando que a recursão pode ser útil aqui para a rainha: f(x)... case "Q": {f("B");f("R")}se a função exigir #includes, essas devem fazer parte da contagem de bytes.
Level River St
4
A fonte nesse gráfico. xD
cjfaure
1
Os movimentos possíveis precisam ser separados por espaços ou as novas linhas também são boas?
Dennis
1
os movimentos legais para um peão são mais complicados do que qualquer outra peça (en passant, captura diagonal e movimento inicial de 2 quadrados). então eu suponho que Jack também tenha as regras de boliche memorizadas?
ardnew

Respostas:

7

GolfScript, 94 93 caracteres

Meu primeiro programa GolfScript! Isso me levou muitas horas se atrapalhando sem realmente saber o que estava fazendo, mas eu persisti e acho que consegui aprender o básico do idioma e jogar bastante bem.

Totalmente jogado :

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

Fonte comentada e mais agradável :

{}/              # 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
}/];

Pode parecer a resposta de Claudiu, porque eu referenciei a resposta dele, bem como a minha solução C (não enviada), enquanto fazia a minha. Ele forneceu uma boa amostra de um programa GolfScript funcional (relativamente) complexo, e isso me ajudou a aprender muito sobre a linguagem. Então, obrigado, Claudiu!

Ainda sendo novo no GolfScript, se vocês tiverem algum feedback, eu gostaria de ouvi-lo!

Runer112
fonte
Impressionante! Bom trabalho =). Vou ter que olhar mais de perto mais tarde para ver como você conseguiu 40 caracteres mais curtos que o meu. Golfscript não é divertido?
Claudiu
12

Python, 217 212 220 217 213 caracteres

Amarrada a solução 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)

Comecei gerando todos os movimentos válidos, mas que cresceram muito, de modo que a abordagem é bastante semelhante à do 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
Claudiu
fonte
Boa extração de caracteres de string com este argumento tupla. Pena que não funciona mais em 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~#)&

Versão não destruída:

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 *)
  ]
)&

Exemplo de uso:

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

A versão sem golfe cria uma pensão completa e, em seguida, seleciona as posições corretas com Cases, enquanto a versão com golfe descarta movimentos inválidos imediatamente no Tablecomando, emitindo ##&[], o que simplesmente desaparece.

Martin Ender
fonte
Apenas curioso sobre a entrada, não é N4d? Não deveria ser Nd4?
devnull
@ Devnull certeza, isso é um erro de digitação. deveria ser Nd4.
Martin Ender
Aprendi uma função conhecida hojeChessboardDistance
swish
De acordo com a documentação do Mathematica / Wolfram Language, "ChessboardDistance [u, v] é equivalente a Max [Abs [uv]]". Talvez você possa salvar caracteres usando o último formulário, especialmente se você substituir Abs [uv] por | uv |.
Michael Stern
@ MichaelStern é exatamente o que estou fazendo na versão golfed;). E infelizmente as barras verticais não funcionam Absno Mathematica, porque denotam alternativas em um padrão.
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]]

Vai ser difícil tocar no Mathematica quando houver jogadas de xadrez: roletes: (m.buettner bem jogado) Retiro tudo isso. Batendo Mathematica por 31!

Última edição: caixa substituída por uma função, filtro embutido na compreensão, para superar a entrada em R;)

uso:

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

Ungolfed (corresponde à versão de 208 caracteres antes de 'u' ser incorporado):

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.
bazzargh
fonte
Você também pode postar uma versão sem armas? (se você tiver um, é claro)
swish
@ swish Eu não, mas não me importo de escrever isso.
bazzargh
@swish done. Espero que tenha mais sentido. Pergunte se você precisa de algo esclarecido.
bazzargh
Bom trabalho! Por que você precisa adicionar pieceà lista [piece,newfile, newrank]se não a usa na correspondência de padrões, pode economizar alguns caracteres?
swish
Está lá para saída. Você verá que eu não faço correspondência de padrões em '... cada movimento possível ...'. Originalmente, eu não tinha isso - os movimentos de xadrez não exigem isso - mas então notei que a pergunta queria, e todo mundo o fazia, então é 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]$'

Como funciona

  • A idéia é representar todos os campos no quadro por um valor numérico, tomando suas coordenadas como um número da base 20 e subtraindo 200. Dessa forma, a1torna-se 20 * 10 + 1 - 200 = 1, h8torna-se 20 * 17 + 8 - 200 = 148, etc.

    Agora, os possíveis movimentos do Bispo podem ser representados por múltiplos (positivos ou negativos) de 19 - a mesma quantidade de passos acima (+20) e para a esquerda (-1) - ou 21 - a mesma quantidade de passos acima (+20 ) e à direita (+1).

    O posicionamento da figura após o movimento é simplesmente a soma de sua posição original e do movimento. Depois de adicionar esses números, temos que verificar se a soma deles corresponde a um campo válido no quadro.

    Como a base (20) é mais que o dobro do número mais alto possível (8), a soma não pode ser agrupada em torno do quadro, por exemplo, mover Bh1 sete etapas para a direita e para cima resultará em uma posição inválida no quadro.

  • A linha

    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 os movimentos possíveis das peças que são representadas por números positivos.

  • Os comandos

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

    armazena o identificador da peça na variável a , a representação numérica da posição original em be as letras a a h na matriz d .

    Após a expansão da cinta, eval{,} echo '$'$atorna-se eval eval echo '$'$a(duplamente mau), que avalia como, por exemplo eval echo $K, qual avalia como echo 1 19 20 21.

  • for i in $c -${c// / -};do …; done circunda todos os movimentos possíveis e suas contrapartes negativas.

  • echo $a${d[$[(i+=b)/20]]}$[i%20] dá a posição final após o movimento.

  • grep '[a-h][1-8]$' garante que temos uma posição válida no conselho.

Dennis
fonte
7

Golfscript, 144 135 caracteres

Em vez de continuar tentando jogar minha solução Python , eu a traduzi para 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}/;;}/

Tradução simples, sem muito golfe, por isso pode ser ainda mais reduzida. Pega a entrada do stdin sem uma nova linha, tente aqui (as primeiras duas linhas são para imitar o stdin).

Claudiu
fonte
Parece funcionar bem! Espero que alguém também tenha uma solução cerebral.
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}}

Alguma sugestão sobre como melhorar isso? Esta é minha primeira vez enviando uma resposta.

calccrypto
fonte
Bem-vindo ao Code Golf! Para começar, você pode remover o espaço em branco no seu código. Lembre-se de que este é um código de golfe, o que implica que o código mais curto vence. Portanto, tente reduzir o tamanho do seu programa.
devnull
Lembre-se de atualizar a contagem de caracteres também!
devnull
@devnull são contados os espaços necessários?
calccrypto
1
Mais uma coisa: Cpode ser bastante simplificado usando o operador ternário ?:e usando o valor de retorno de printf. ( printfretorna o número de caracteres escritos, portanto, neste caso, é sempre diferente de zero.) C(P,c,r){return(0<=c)&(c<8)&(0<r)&(r<9)?printf("%c%c%d ",P,c+'a',r):0;}. Uma edição menor: há um espaço extra Mapós o ifque você pode remover.
user12205
1
No momento, você parece não estar contando nenhuma nova linha. Enquanto alguns deles podem ser removidos, outros não. As novas linhas necessárias devem contribuir definitivamente para a contagem de bytes.
Dennis
3

Haskell, 300 269 ​​caracteres

Obrigado a bazzargh pela ajuda na perda de 31 caracteres ...

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}

Mesmo algoritmo que a versão Mathematica. Saída de amostra do ghci:

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

(Você não pediu verificação de sanidade!)

Alexander Hanysz
fonte
Você pode se livrar do espaço em branco sintático. Veja minha resposta aqui: codegolf.stackexchange.com/questions/19255/… (para ser mais específico, você deseja que {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)

Chamado usando a jfunção

j "Nd4"

Não trabalho com Haskell há alguns meses, por isso não acabou sendo tão curto quanto a maioria das outras soluções, mas tenho certeza de que há algumas otimizações a serem feitas, principalmente h. Eu posso reduzi-lo um pouco.

Silvio Mayolo
fonte
1

perguntas e respostas [ 311 262 caracteres]

Existe o potencial de reduzir mais alguns caracteres. Vou reduzi-lo na próxima iteração.

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

Rei

g"ka1"
`a2`b1`b2

Cavaleiro

g"na1"
`b3`c2

Bispo

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

Rainha

g"qa1"
`a2`a3`a4`a5`a6`a7`a8`b1`b2`c1`c3`d1`d4`e1`e5`f1`f6`g1`g7`h1`h8
Nyi
fonte
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="")}

Versão não destruída:

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"

A solução é até boa legível. No entanto, adicionei alguns parênteses e comentários para os leitores que não estão familiarizados com o código R (na versão ungolfed).

lambruscoAcido
fonte
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))"ਲ਼ੁߏߚߙÈേെ൅ൄൃ൙൪ൻඌඝථ඿౿౾౽౼౻౺౹ಐಏಠಞರಭೀ಼೐ೋೠ೚೰೩"

Infelizmente, todos os compiladores Haskell em que posso colocar minhas mãos agora têm problemas com literais de seqüência de caracteres Unicode. Aqui está a versão (mais longa) 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"

A definição h x y=...é uma função hash; movimentos válidos serão hash para números de caracteres que estão na sequência de 41 caracteres. Isso elimina a necessidade de uma declaração "case" ou equivalente.

Não estou planejando trabalhar mais nisso agora. Seria divertido ver se alguém pode usar uma função de hash em uma linguagem mais concisa para criar uma solução mais curta.

Alexander Hanysz
fonte