Dimmi le mosse


28

Jack e Jane decisero di giocare a scacchi per passare il tempo. Sfortunatamente, Jack è piuttosto cattivo nel visualizzare. Trova difficile capire le mosse possibili per un dato pezzo diverso da una pedina, ovviamente!

La tua sfida è di aiutare a trovare a Jack le possibili opzioni per un dato pezzo (diverso da una pedina).

Nel caso in cui uno ha dimenticato, i vari pezzi sono indicati da:

  • K: Re
  • Q: Queen
  • N: Cavaliere
  • B: vescovo
  • R: Torre

A titolo di esempio, nella figura seguente il cavaliere si trova d4e può spostarsi c2, b3, b5, c6, e6, f5, f3, e2. Per un dato input:

Nd4

produrrai:

Nc2 Nb3 Nb5 Nc6 Ne6 Nf5 Nf3 Ne2

inserisci qui la descrizione dell'immagine

Regole:

  • L'ordine dell'output non ha importanza fino a quando sono elencate tutte le mosse possibili
  • Le mosse possibili possono essere separate da spazi bianchi, newline o qualsiasi altro delimitatore
  • L'ingresso può essere passato al programma come parametro o via STDIN
  • Gli spazi bianchi nel programma devono essere conteggiati, quindi sfruttali in modo ottimale

Questo è il codice golf. (Evitare di utilizzare qualsiasi strumento / utilità appositamente progettato per lo scopo.) Vince la risposta più breve!


1
Credo che funzionerebbe perfettamente come un codice golf
John Dvorak,

3
Il codice golf è la scelta migliore. L'ovvio viene sempre dimenticato: capisco che possiamo inviare una funzione o un programma e che l'input / output può essere sia stdin / stout che parametri / valore di ritorno. Sto pensando che la ricorsione potrebbe essere utile qui per la regina: f(x)... case "Q": {f("B");f("R")}se la funzione richiede #include, questi dovrebbero far parte del conteggio dei byte.
Level River St

4
Il carattere in quella grafica. xD
cjfaure,

1
Le mosse possibili devono essere separate da spazi o anche i newline sono OK?
Dennis,

1
le mosse legali per un pedone sono più contorte di qualsiasi altro pezzo (en passant, cattura diagonale e mossa iniziale a 2 quadrati). quindi presumo che Jack abbia anche memorizzato le regole del castling?
Ardnew,

Risposte:


7

GolfScript, 94 93 caratteri

Il mio primo programma GolfScript in assoluto! Mi ci sono volute molte ore a armeggiare senza sapere davvero cosa stavo facendo, ma ho persistito e penso di essere riuscito a imparare le basi della lingua e a golf abbastanza bene.

Completamente golf :

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

Fonte commentata e più bella :

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

Potrebbe sembrare la risposta di Claudiu, perché ho fatto riferimento alla sua risposta, così come alla mia (non inviata) soluzione C, mentre facevo la mia. Ha fornito un buon esempio di un programma (relativamente) complesso, funzionante GolfScript, e mi ha aiutato a imparare molto sulla lingua. Quindi grazie, Claudiu!

Essendo ancora nuovo su GolfScript, se avete commenti, apprezzerei ascoltarlo!


Eccezionale! Bel lavoro =). Dovrò esaminarlo più da vicino in seguito per vedere come hai ottenuto 40 caratteri in meno del mio. Golfscript non è divertente?
Claudiu,

12

Python, 217 212 220 217 213 caratteri

Legata la soluzione Mathematica a 213 byte

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)

Ho iniziato generando tutte le mosse valide ma che sono diventate troppo grandi, quindi l'approccio è abbastanza simile a quello di 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

Bella estrazione di caratteri stringa con questa tupla argomento. Peccato che non funziona più in Python 3.
Evpok,

10

Mathematica, 278 272 264 260 215 213 caratteri

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

Versione non golfata:

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

Esempio di utilizzo:

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

La versione non golfata crea una pensione completa, quindi seleziona le posizioni corrette con Cases, mentre la versione golfata rilascia immediatamente mosse non valide nel Tablecomando emettendo ##&[], che svanisce semplicemente.


Solo curioso di sapere l'input, vero N4d? Non dovrebbe essere Nd4invece?
Devnull

@ sicuramente non è un errore di battitura. dovrebbe essere Nd4.
Martin Ender,

Ho imparato una funzione conosciuta oggiChessboardDistance
swish

Secondo la documentazione di Mathematica / Wolfram Language, "ChessboardDistance [u, v] è equivalente a Max [Abs [uv]]." Forse puoi salvare i caratteri usando quest'ultimo modulo, specialmente se sostituisci Abs [uv] con | uv |.
Michael Stern,

@MichaelStern è esattamente quello che sto facendo nella versione golf;). E sfortunatamente le barre verticali non funzionano Absin Mathematica, perché indicano delle alternative in uno schema.
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]]

Sarà difficile toccare Mathematica quando ci sono mosse di scacchi incorporate: rollseyes: (m.buettner ben giocato) tutto. Battere Mathematica per 31!

Ultima modifica: ha sostituito il caso con una funzione, il filtro integrato è compreso, per battere la voce in R;)

utilizzo:

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

Ungolfed (corrisponde alla versione 208 char prima che 'u' fosse inline):

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.

Puoi pubblicare anche una versione non giocata? (se ne hai uno ovviamente)
swish

@swish Non lo so, ma non mi dispiace scriverlo.
bazzargh,

@ fatto fatto. Spero che abbia più senso. Chiedi se hai bisogno di qualcosa di chiarito.
bazzargh,

Ottimo lavoro! Perché è necessario aggiungere pieceall'elenco [piece,newfile, newrank]se non lo si utilizza nella corrispondenza dei motivi, è possibile salvare alcuni caratteri?
swish

È lì per l'output. Vedrai che non modifico la corrispondenza su di esso in "... ogni possibile mossa ...". Inizialmente non avevo questo - le mosse di scacchi non lo richiedono - ma poi ho notato che la domanda lo voleva, e lo facevano tutti gli altri, quindi è giusto.
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]$'

Come funziona

  • L'idea è di rappresentare ogni campo sul tabellone con un valore numerico, prendendo le sue coordinate come un numero base-20 e sottraendo 200. In questo modo, a1diventa 20 * 10 + 1 - 200 = 1, h8diventa 20 * 17 + 8 - 200 = 148, ecc.

    Ora, le possibili mosse del Vescovo possono essere rappresentate da multipli (positivi o negativi) di 19 - stessa quantità di gradini su (+20) e verso sinistra (-1) - o 21 - stessa quantità di gradini su (+20 ) e a destra (+1).

    La posizione della figura dopo lo spostamento è semplicemente la somma della sua posizione originale e del movimento. Dopo aver aggiunto quei numeri, dobbiamo verificare se la loro somma corrisponde a un campo valido sul tabellone.

    Poiché la base (20) è più del doppio rispetto al numero più alto possibile (8), la somma non può avvolgersi attorno alla scacchiera, ad esempio spostando Bh1 di sette passi verso destra e verso l'alto si otterrà una posizione della scacchiera non valida.

  • La linea

    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 tutte le possibili mosse dei pezzi che sono rappresentati da numeri positivi.

  • I comandi

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

    memorizza l'identificatore del pezzo nella variabile a , la rappresentazione numerica della posizione originale in b e le lettere dalla a alla h nella matrice d .

    Dopo l'espansione del rinforzo, eval{,} echo '$'$adiventa eval eval echo '$'$a(doppiamente malvagio), che valuta, ad esempio eval echo $K, che valuta echo 1 19 20 21.

  • for i in $c -${c// / -};do …; done avvolge tutti i possibili movimenti e le loro controparti negative.

  • echo $a${d[$[(i+=b)/20]]}$[i%20] dà la posizione finale dopo il movimento.

  • grep '[a-h][1-8]$' si assicura che abbiamo una posizione del consiglio valida.


7

Golfscript, 144 135 caratteri

Invece di continuare a provare a golf la mia soluzione Python , l'ho tradotto in 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}/;;}/

Traduzione semplice senza molto golf, quindi molto probabilmente può essere ridotta ulteriormente. Prende input da stdin senza una nuova riga, provalo qui (le prime due righe sono per imitare lo stdin).


Sembra funzionare bene! Spero che qualcuno trovi anche una soluzione brainf * ck.
Devnull

6

C 634 632 629 625 600 caratteri

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

Qualche suggerimento su come migliorare questo? Questa è la prima volta che invio una risposta.


Benvenuti in Code Golf! Per cominciare, è possibile eliminare gli spazi bianchi nel codice. Ricorda che questo è il codice golf, il che implica che vince il codice più corto. Quindi cerca di ridurre le dimensioni del tuo programma.
Devnull

Ricorda di aggiornare anche il conteggio dei personaggi!
Devnull

@devnull sono contati gli spazi necessari?
calccrypto,

1
Ancora una cosa: Cpuò essere notevolmente semplificato usando l'operatore ternario ?:e usando il valore di ritorno di printf. ( printfrestituisce il numero di caratteri scritti, quindi in questo caso è sempre diverso da zero.) C(P,c,r){return(0<=c)&(c<8)&(0<r)&(r<9)?printf("%c%c%d ",P,c+'a',r):0;}. Una modifica minore: c'è uno spazio extra Mdopo ifche è possibile rimuovere.
user12205

1
In questo momento, sembra che non si stia contando nessuna nuova riga. Mentre alcuni possono essere rimossi, altri no. Le nuove righe richieste dovrebbero sicuramente contribuire al conteggio dei byte.
Dennis,

3

Haskell, 300 269 ​​caratteri

Grazie a bazzargh per l'aiuto nella perdita di 31 caratteri ...

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}

Stesso algoritmo della versione di Mathematica. Esempio di output di ghci:

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

(Non hai chiesto il controllo della sanità mentale!)


Puoi liberarti dello spazio bianco sintattico. Vedi la mia risposta qui: codegolf.stackexchange.com/questions/19255/… (per essere più precisi, vuoi che {h = d (x !! 1) (y !! 1); ...})
bazzargh

1

Haskell, 446 caratteri

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)

Chiamato utilizzando la jfunzione

j "Nd4"

Non lavoro con Haskell da alcuni mesi, quindi non è stato così breve come la maggior parte delle altre soluzioni, ma sono sicuro che ci sono alcune ottimizzazioni da apportare, principalmente con h. Potrei accorciarlo un po '.


1

domande e risposte [ 311 262 caratteri]

Esiste il potenziale di ridurre alcuni altri personaggi. Lo ridurrò nella prossima iterazione.

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

re

g"ka1"
`a2`b1`b2

Cavaliere

g"na1"
`b3`c2

vescovo

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

Regina

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 caratteri

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

Versione non golfata:

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 soluzione è persino buona lettura. Tuttavia ho aggiunto alcune parentesi e commenti per lettori che non hanno familiarità con il codice R (nella versione non golfata).


0

Haskell (ipotetico), 248 caratteri

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

Sfortunatamente, ogni compilatore Haskell su cui riesco a mettere le mani adesso ha problemi con i letterali di stringhe Unicode. Ecco la versione (più lunga) che funziona davvero:

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 definizione h x y=...è una funzione hash; le mosse valide avranno l'hash sui numeri di caratteri che si trovano nella stringa di 41 caratteri. Questo elimina la necessità di un'istruzione "case" o equivalente.

Non ho intenzione di lavorare ulteriormente su questo adesso. Sarebbe divertente vedere se qualcuno può usare una funzione hash in un linguaggio più conciso per fare una soluzione più breve.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.