Dites-moi les mouvements

28

Jack et Jane ont décidé de jouer aux échecs pour s'absenter. Malheureusement, Jack est plutôt mauvais à visualiser. Il trouve difficile de comprendre les mouvements possibles pour une pièce donnée autre qu'un pion, bien sûr!

Votre défi consiste à aider Jack à trouver les options possibles pour une pièce donnée (autre qu'un pion).

En cas d'oubli, les différentes pièces sont désignées par:

  • K: King
  • Q: Reine
  • N: Knight
  • B: évêque
  • R: Tour

À titre d'exemple, dans l'image du chevalier est situé à d4et peut se déplacer à c2, b3, b5, c6, e6, f5, f3, e2. Pour une entrée donnée:

Nd4

vous produiriez:

Nc2 Nb3 Nb5 Nc6 Ne6 Nf5 Nf3 Ne2

entrez la description de l'image ici

Règles:

  • L'ordre de sortie n'a pas d'importance tant que tous les mouvements possibles sont répertoriés
  • Les déplacements possibles peuvent être séparés par des espaces, des sauts de ligne ou tout autre délimiteur
  • L'entrée peut être transmise au programme en tant que paramètre ou via STDIN
  • Les espaces dans le programme doivent être comptés, alors utilisez-les de manière optimale

C'est le golf de code. (Veuillez éviter d'utiliser des outils / utilitaires spécialement conçus à cet effet.) La réponse la plus courte l'emporte!

devnull
la source
1
Je crois que cela fonctionnerait très bien comme un golf de code
John Dvorak
3
Le golf de code est le meilleur choix. L'évidence est toujours oubliée: je comprends que nous pouvons soumettre une fonction ou un programme, et que l'entrée / sortie peut être soit stdin / stout, soit parameters / return value. Je pense que la récursivité pourrait être utile ici pour la reine: f(x)... case "Q": {f("B");f("R")}si la fonction nécessite un #includes, ceux-ci devraient faire partie du nombre d'octets.
Level River St
4
La police dans ce graphique. xD
cjfaure
1
Les déplacements possibles doivent-ils être séparés par des espaces ou les sauts de ligne sont-ils également acceptés?
Dennis
1
les mouvements légaux pour un pion sont plus compliqués que n'importe quelle autre pièce (en passant, capture diagonale et mouvement initial de 2 cases). donc je suppose que jack a également mémorisé les règles du roque?
ardnew

Réponses:

7

GolfScript, 94 93 caractères

Mon tout premier programme GolfScript! Cela m'a pris plusieurs heures à tâtonner sans vraiment savoir ce que je faisais, mais j'ai persisté et je pense que j'ai réussi à apprendre les bases de la langue et à le jouer assez bien.

Entièrement golfé :

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

Source commentée et plus agréable :

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

Cela peut ressembler à la réponse de Claudiu, parce que j'ai référencé sa réponse, ainsi que ma solution C (non soumise), tout en faisant la mienne. Il a fourni un bon exemple d'un programme GolfScript (relativement) complexe et fonctionnel, et cela m'a aidé à en apprendre beaucoup sur le langage. Alors merci, Claudiu!

Étant encore nouveau sur GolfScript, si vous avez des commentaires, j'apprécierais de l'entendre!

Runer112
la source
Impressionnant! Beau travail =). Je devrai y regarder de plus près plus tard pour voir comment vous avez obtenu 40 caractères plus courts que le mien. Golfscript n'est-il pas amusant?
Claudiu
12

Python, 217 212 220 217 213 caractères

Lié la solution Mathematica à 213 octets

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)

J'ai commencé par générer tous les mouvements valides mais qui sont devenus trop importants, donc l'approche est assez similaire à celle 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
Claudiu
la source
Belle extraction des caractères de chaîne avec cet argument tuple. Dommage que cela ne fonctionne plus en Python 3.
Evpok
10

Mathematica, 278 272 264 260 215 213 caractères

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~#)&

Version non golfée:

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

Exemple d'utilisation:

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

La version non golfée crée une carte complète, puis sélectionne les positions correctes avec Cases, tandis que la version golfée supprime immédiatement les mouvements invalides dans la Tablecommande en émettant ##&[], ce qui disparaît simplement.

Martin Ender
la source
Je suis juste curieux de savoir ce que c'est, n'est-ce pas N4d? Ne devrait-il pas en être ainsi Nd4?
devnull
@devnull bien sûr, c'est une faute de frappe. devrait être Nd4.
Martin Ender
A appris une fonction connue aujourd'huiChessboardDistance
swish
Selon la documentation Mathematica / Wolfram Language, "ChessboardDistance [u, v] est équivalent à Max [Abs [uv]]." Vous pouvez peut-être enregistrer des caractères en utilisant ce dernier formulaire, surtout si vous remplacez Abs [uv] par | uv |.
Michael Stern
@MichaelStern c'est exactement ce que je fais dans la version golfée;). Et malheureusement, les barres verticales ne fonctionnent pas Absdans Mathematica, car elles dénotent des alternatives dans un motif.
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]]

Ça va être difficile de toucher à Mathematica quand cela aura des mouvements d'échecs intégrés: rollseyes: (bien joué m.buettner) Je reprends tout. Battre Mathematica par 31!

Dernière modification: cas remplacé par une fonction, filtre intégré à la compréhension, pour battre l'entrée dans R;)

usage:

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

Non golfé (correspond à la version 208 caractères avant que le «u» ne soit inséré):

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
la source
Pouvez-vous également publier une version non golfée? (si vous en avez un bien sûr)
swish
@swish je ne le fais pas, mais cela ne me dérange pas d'écrire cela.
bazzargh
@swish done. J'espère que cela a du sens. Demandez si vous avez besoin de clarifier quelque chose.
bazzargh
Bon travail! Pourquoi avez-vous besoin d'ajouter pieceà la liste [piece,newfile, newrank]si vous ne l'utilisez pas dans la correspondance de motifs, pouvez-vous enregistrer certains caractères?
Swish
Il est là pour la sortie. Vous verrez que je ne fais pas correspondre les motifs dessus dans «... chaque mouvement possible ...». À l'origine, je n'avais pas cela - les mouvements d'échecs ne l'exigent pas - mais j'ai remarqué que la question le voulait, et tout le monde l'a fait, donc c'est juste.
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]$'

Comment ça marche

  • L'idée est de représenter chaque champ du tableau par une valeur numérique, en prenant ses coordonnées comme un nombre en base 20 et en soustrayant 200. De cette façon, a1devient 20 * 10 + 1 - 200 = 1, h8devient 20 * 17 + 8 - 200 = 148, etc.

    Maintenant, les mouvements possibles de l'évêque peuvent être représentés par des multiples (positifs ou négatifs) de 19 - même quantité de pas vers le haut (+20) et vers la gauche (-1) - ou 21 - même quantité de pas vers le haut (+20 ) et à droite (+1).

    Le placement de la figure après le mouvement est simplement la somme de sa position d'origine et du mouvement. Après avoir ajouté ces chiffres, nous devons vérifier si leur somme correspond à un champ valide sur le tableau.

    Étant donné que la base (20) est plus de deux fois plus grande que le nombre le plus élevé possible (8), la somme ne peut pas enrouler autour de la planche, par exemple, déplacer Bh1 de sept pas vers la droite et vers le haut entraînera une position de planche invalide.

  • La ligne

    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
    

    énumère tous les mouvements possibles des pièces qui sont représentées par des nombres positifs.

  • Les commandes

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

    stocke l'identifiant de la pièce dans la variable a , la représentation numérique de la position d'origine dans b et les lettres a à h dans le tableau d .

    Après l'expansion de l'accolade, eval{,} echo '$'$adevient eval eval echo '$'$a(doublement mauvais), qui évalue à, par exemple eval echo $K, qui évalue à echo 1 19 20 21.

  • for i in $c -${c// / -};do …; done boucle sur tous les mouvements possibles et leurs homologues négatifs.

  • echo $a${d[$[(i+=b)/20]]}$[i%20] donne la position finale après le mouvement.

  • grep '[a-h][1-8]$' s'assure que nous avons un poste de conseil valide.

Dennis
la source
7

Golfscript, 144 135 caractères

Au lieu de continuer à essayer de jouer au golf avec ma solution Python , je l'ai traduite en 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}/;;}/

Traduction simple sans beaucoup de golf, il peut donc être encore plus réduit. Prend l'entrée de stdin sans nouvelle ligne, essayez-le ici (les deux premières lignes sont pour imiter stdin).

Claudiu
la source
Semble bien fonctionner! J'espère que quelqu'un trouvera aussi une solution brainf * ck.
devnull
6

C 634 632 629 625 600 caractères

#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}}

Des suggestions sur la façon d'améliorer cela? C'est la première fois que je soumets une réponse.

calccrypto
la source
Bienvenue chez Code Golf! Pour commencer, vous pouvez supprimer les espaces dans votre code. N'oubliez pas qu'il s'agit de code golf, ce qui implique que le code le plus court l'emporte. Essayez donc de réduire la taille de votre programme.
devnull
N'oubliez pas de mettre à jour le nombre de caractères aussi!
devnull
@devnull les espaces nécessaires sont-ils comptés?
calccrypto
1
Une dernière chose: Cpeut être grandement simplifié en utilisant l'opérateur ternaire ?:et en utilisant la valeur de retour de printf. ( printfrenvoie le nombre de caractères écrits, dans ce cas, il est toujours différent de zéro.) C(P,c,r){return(0<=c)&(c<8)&(0<r)&(r<9)?printf("%c%c%d ",P,c+'a',r):0;}. Une modification mineure: il y a un espace supplémentaire Maprès celui ifque vous pouvez supprimer.
user12205
1
En ce moment, vous semblez ne pas compter de nouvelles lignes. Alors que certains d'entre eux peuvent être enlevés, d' autres ne peuvent pas. Les sauts de ligne requis devraient certainement contribuer au nombre d'octets.
Dennis
3

Haskell, 300 269 ​​caractères

Merci à bazzargh pour son aide à perdre 31 personnages ...

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}

Même algorithme que la version Mathematica. Exemple de sortie de ghci:

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

(Vous n'avez pas demandé de vérification d'esprit!)

Alexander Hanysz
la source
Vous pouvez vous débarrasser des espaces syntaxiques. Voir ma réponse ici: codegolf.stackexchange.com/questions/19255/… (pour être plus précis, vous voulez laisser {h = d (x !! 1) (y !! 1); ...})
bazzargh
1

Haskell, 446 caractères

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)

Appelé à l'aide de la jfonction

j "Nd4"

Je n'ai pas travaillé avec Haskell depuis quelques mois, donc cela n'a pas été aussi court que la plupart des autres solutions, mais je suis sûr qu'il y a des optimisations à faire, principalement avec h. Je pourrais le raccourcir un peu.

Silvio Mayolo
la source
1

q & k [ 311 262 caractères]

Il y a un potentiel de réduction de quelques caractères supplémentaires. Je vais le réduire à la prochaine itération.

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}

Usage

Tour

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

Roi

g"ka1"
`a2`b1`b2

Chevalier

g"na1"
`b3`c2

Évêque

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

Reine

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

R, 203 caractères

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="")}

Version non golfée:

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="")
}

Usage:

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

La solution est même bien lisible. Cependant, j'ai ajouté des parenthèses et des commentaires pour les lecteurs peu familiers avec le code R (sur la version non golfée).

lambruscoAcido
la source
0

Haskell (hypothétique), 248 caractères

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

Malheureusement, chaque compilateur Haskell sur lequel je peux mettre la main en ce moment a des problèmes avec les littéraux de chaîne Unicode. Voici la version (plus longue) qui fonctionne réellement:

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 définition h x y=...est une fonction de hachage; les mouvements valides hachent les numéros de caractères qui sont dans la chaîne de 41 caractères. Cela supprime la nécessité d'une déclaration "case" ou équivalent.

Je ne prévois pas de continuer à travailler là-dessus pour le moment. Ce serait amusant de voir si quelqu'un peut utiliser une fonction de hachage dans un langage plus concis pour faire une solution plus courte.

Alexander Hanysz
la source