Powiedz mi ruchy

28

Jack i Jane postanowili zagrać w szachy, aby spędzić czas z dala. Niestety, Jack jest kiepski w wizualizacji. Oczywiście ciężko jest mu określić ruchy danego pionka innego niż pionek!

Twoim wyzwaniem jest pomoc Jackowi w znalezieniu możliwych opcji dla danego pionka (innego niż pionek).

W przypadku zapomnienia różne elementy są oznaczone:

  • K: King
  • P: Królowa
  • N: Rycerz
  • B: Biskupie
  • R: Gawron

Jako przykład, na poniższym obrazie skoczek znajduje się na d4i może poruszać się c2, b3, b5, c6, e6, f5, f3, e2. Dla danych wejściowych:

Nd4

wyprodukowałbyś:

Nc2 Nb3 Nb5 Nc6 Ne6 Nf5 Nf3 Ne2

wprowadź opis zdjęcia tutaj

Zasady:

  • Kolejność danych wyjściowych nie ma znaczenia, dopóki wymienione są wszystkie możliwe ruchy
  • Możliwe ruchy można rozdzielić spacjami, znakami nowej linii lub dowolnym innym ogranicznikiem
  • Dane wejściowe można przekazać do programu jako parametr lub przez STDIN
  • Białe spacje w programie będą liczone, więc optymalnie je wykorzystaj

To jest kod golfowy. (Unikaj korzystania z narzędzi / narzędzi specjalnie zaprojektowanych do tego celu.) Zwycięża najkrótsza odpowiedź!

diabelnie
źródło
1
Wierzę, że to zadziałałoby dobrze jako golf golfowy
John Dvorak
3
Code golf to lepszy wybór. Oczywiste jest zawsze zapominane: Rozumiem, że możemy przesłać albo funkcję, albo program, a wejście / wyjście może być albo standardowym / grubym, albo parametrami / zwracaną wartością. Myślę, że rekurencja może się tu przydać królowej: f(x)... case "Q": {f("B");f("R")}jeśli funkcja wymaga któregokolwiek #include, powinny one być częścią liczby bajtów.
Level River St
4
Czcionka na tej grafice. xD
cjfaure
1
Czy możliwe ruchy muszą być oddzielone spacjami, czy też nowe znaki są w porządku?
Dennis
1
legalne ruchy pionka są bardziej skomplikowane niż jakikolwiek inny element (en passant, ukośne przejmowanie i początkowy ruch o 2 pola). więc zakładam, że Jack zapamiętał również zasady roszowania?
nowy

Odpowiedzi:

7

GolfScript, 94 93 znaków

Mój pierwszy w historii program GolfScript! Zajęło mi to wiele godzin grzebania w głowie, nie bardzo wiedząc, co robię, ale upierałem się i myślę, że udało mi się nauczyć podstaw języka i dość dobrze grać w golfa.

W pełni golfa :

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

Skomentowane i ładniejsze źródło :

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

Może to wyglądać jak odpowiedź Claudiu, ponieważ odniosłem się do jego odpowiedzi, a także do mojego (nieprzesłanego) rozwiązania C podczas tworzenia mojej. Dostarczył dobry przykład (względnie) złożonego, działającego programu GolfScript, który pomógł mi wiele nauczyć się o języku. Dziękuję, Claudiu!

Będąc nowym w GolfScript, jeśli macie jakieś uwagi, chętnie je usłyszę!

Runer112
źródło
Niesamowite! Dobra robota =). Będę musiał przyjrzeć się temu dokładniej później, aby zobaczyć, w jaki sposób masz 40 znaków krótszych niż moje. Czy Golfscript nie jest zabawny?
Claudiu
12

Python, 217 212 220 217 213 znaków

Powiązano 213-bajtowe rozwiązanie Mathematica

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)

Zacząłem od wygenerowania wszystkich prawidłowych ruchów, ale stało się to zbyt duże, więc podejście jest dość podobne 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
źródło
Ładne wyodrębnianie ciągów znaków za pomocą tej krotki argumentu. Szkoda, że ​​nie działa już w Pythonie 3.
Evpok
10

Mathematica, 278 272 264 260 215 213 znaków

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

Wersja bez golfa:

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

Przykładowe użycie:

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

Wersja bez golfa tworzy pełne wyżywienie, a następnie wybiera prawidłowe pozycje za pomocą Cases, podczas gdy wersja z golfem natychmiast odrzuca nieprawidłowe ruchy w Tablepoleceniu, wydając ##&[], co po prostu znika.

Martin Ender
źródło
Ciekawe, co to jest, prawda N4d? Czy nie powinno tak być Nd4?
devnull
@devnull na pewno, to literówka. powinno być Nd4.
Martin Ender
Nauczyłem się dzisiaj ChessboardDistance
znanej
Według dokumentacji języka Mathematica / Wolfram „ChessboardDistance [u, v] jest równoważne Maxowi [Abs [uv]].” Być może możesz uratować postacie, korzystając z tego ostatniego formularza, zwłaszcza jeśli zamienisz Abs [uv] na | uv |.
Michael Stern
@MichaelStern właśnie to robię w wersji golfowej;). I niestety pionowe paski nie działają Absw Mathematica, ponieważ oznaczają alternatywy we wzorze.
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]]

Trudno będzie dotknąć Mathematiki, kiedy ma wbudowane ruchy szachowe: rollseyes: (dobrze zagrany m.buettner) Cofam to wszystko. Pokonanie Mathematiki o 31!

Ostatnia edycja: zastąpiono wielkość liter funkcją, wbudowano filtr do zrozumienia, aby pobić wpis w R;)

stosowanie:

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

Niegolfowany (odpowiada wersji 208 znaków przed wstawieniem „u”):

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
źródło
Czy możesz też opublikować wersję bez golfa? (jeśli masz, oczywiście)
świst
@ Swish Nie, ale nie mam nic przeciwko, aby to napisać.
bazzargh
@ Swish gotowe. Mam nadzieję, że to ma sens. Zapytaj, czy potrzebujesz czegoś wyjaśnionego.
bazzargh
Dobra robota! Dlaczego potrzebujesz dodać piecedo listy, [piece,newfile, newrank]jeśli nie używasz jej do dopasowywania wzorców, może zaoszczędzić ci kilka znaków?
świst
Jest tam na wyjście. Zobaczysz, że nie dopasowuję do niego wzoru w „... każdym możliwym ruchu ...”. Początkowo nie miałem tego - ruchy szachowe tego nie wymagają - ale potem zauważyłem, że pytanie tego chce i wszyscy inni to zrobili, więc jest to sprawiedliwe.
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]$'

Jak to działa

  • Chodzi o to, aby przedstawić każde pole na planszy wartością liczbową, biorąc jego współrzędne jako liczbę podstawową-20 i odejmując 200. W ten sposób a1staje się 20 * 10 + 1 - 200 = 1, h8staje się 20 * 17 + 8 - 200 = 148itp.

    Teraz możliwe ruchy gońca mogą być reprezentowane przez (dodatnie lub ujemne) wielokrotności 19 - tyle samo kroków w górę (+20) i w lewo (-1) - lub 21 - tyle samo kroków w górę (+20 ) i po prawej stronie (+1).

    Położenie figurki po ruchu jest po prostu sumą jej pierwotnej pozycji i ruchu. Po dodaniu tych liczb musimy sprawdzić, czy ich suma odpowiada prawidłowemu polu na tablicy.

    Ponieważ podstawa (20) jest ponad dwa razy większa niż najwyższa możliwa liczba (8), suma nie może owijać się wokół planszy, np. Przesunięcie Bh1 o siedem kroków w prawo i w górę spowoduje nieprawidłowe ustawienie planszy.

  • Linia

    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
    

    wylicza wszystkie możliwe ruchy elementów, które są reprezentowane przez liczby dodatnie.

  • Polecenia

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

    przechowuje identyfikator elementu w zmiennej a , reprezentację numeryczną pierwotnej pozycji wb oraz litery od a do h w tablicy d .

    Po rozwinięciu nawiasu klamrowego eval{,} echo '$'$astaje się eval eval echo '$'$a(podwójnie zły), który ocenia np. eval echo $K, Który ocenia echo 1 19 20 21.

  • for i in $c -${c// / -};do …; done zapętla wszystkie możliwe ruchy i ich negatywne odpowiedniki.

  • echo $a${d[$[(i+=b)/20]]}$[i%20] daje ostateczną pozycję po ruchu.

  • grep '[a-h][1-8]$' upewnia się, że mamy prawidłową pozycję na pokładzie.

Dennis
źródło
7

Golfscript, 144 135 znaków

Zamiast kontynuować grę w golfa w moim języku Python , przetłumaczyłem go na 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}/;;}/

Proste tłumaczenie bez dużej gry w golfa, więc najprawdopodobniej może zostać jeszcze bardziej oddalone. Pobiera dane wejściowe ze standardowego wejścia bez nowego wiersza, spróbuj tutaj (pierwsze dwie linie mają naśladować standardowe wejście standardowe).

Claudiu
źródło
Wydaje się działać dobrze! Mam nadzieję, że ktoś również wymyśli rozwiązanie typu brainf * ck.
devnull
6

C 634 632 629 625 600 znaków

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

Wszelkie sugestie, jak to poprawić? Po raz pierwszy przesyłam odpowiedź.

calccrypto
źródło
Witamy w Code Golf! Na początek możesz usunąć białe znaki w kodzie. Pamiętaj, że to kod golfowy, co oznacza, że ​​wygrywa najkrótszy kod. Więc spróbuj zmniejszyć rozmiar swojego programu.
devnull
Pamiętaj też o aktualizacji liczby postaci!
devnull
@devnull są liczone niezbędne spacje?
calccrypto
1
Jeszcze jedno: Cmożna znacznie uprościć, używając operatora trójskładnikowego ?:i wartości zwracanej printf. ( printfzwraca liczbę zapisanych znaków, więc w tym przypadku jest zawsze niezerowa) C(P,c,r){return(0<=c)&(c<8)&(0<r)&(r<9)?printf("%c%c%d ",P,c+'a',r):0;}. Drobna edycja: Mpo iftym można usunąć dodatkowe miejsce .
user12205
1
W tej chwili wydaje się, że nie liczysz żadnych nowych linii. Podczas gdy niektóre z nich można usunąć, inne nie. Wymagane nowe wiersze powinny zdecydowanie przyczynić się do liczby bajtów.
Dennis
3

Haskell, 300 269 ​​znaków

Dzięki bazzargh za pomoc w utracie 31 znaków ...

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}

Ten sam algorytm co wersja Mathematica. Przykładowe dane wyjściowe z ghci:

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

(Nie poprosiłeś o sprawdzenie rozsądku!)

Alexander Hanysz
źródło
Możesz pozbyć się składniowych białych znaków. Zobacz moją odpowiedź tutaj: codegolf.stackexchange.com/questions/19255/... (ściślej mówiąc, chcesz pozwolić {h = d (x !! 1) (y !! 1); ...})
bazzargh
1

Haskell, 446 znaków

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)

Wywoływany za pomocą jfunkcji

j "Nd4"

Nie pracowałem z Haskellem od kilku miesięcy, więc nie było tak krótkie jak większość innych rozwiązań, ale jestem pewien, że są pewne optymalizacje, głównie z h. Mogę to trochę skrócić.

Silvio Mayolo
źródło
1

q & k [ 311 262 znaków]

Istnieje potencjał zmniejszenia liczby kolejnych postaci. Zmniejszę to w następnej iteracji.

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}

Stosowanie

Wieża

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

Król

g"ka1"
`a2`b1`b2

Rycerz

g"na1"
`b3`c2

Biskup

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

królowa

g"qa1"
`a2`a3`a4`a5`a6`a7`a8`b1`b2`c1`c3`d1`d4`e1`e5`f1`f6`g1`g7`h1`h8
nyi
źródło
0

R, 203 znaków

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

Wersja bez golfa:

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

Stosowanie:

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

Rozwiązanie jest nawet dobrze czytelne. Dodałem jednak nawiasy i komentarze dla czytelników niezaznajomionych z kodem R (w wersji bez golfisty).

lambruscoAcido
źródło
0

Haskell (hipotetyczny), 248 znaków

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

Niestety, każdy kompilator Haskell, który mogę teraz zdobyć, ma problemy z literałami łańcuchowymi Unicode. Oto (dłuższa) wersja, która faktycznie działa:

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"

Definicja h x y=...jest funkcją skrótu; poprawne ruchy będą mieszały się z liczbami znaków, które zawierają 41 znaków. Dzięki temu nie trzeba używać instrukcji „case” lub jej odpowiednika.

Nie planuję teraz dalej nad tym pracować. Byłoby fajnie zobaczyć, czy ktoś może użyć funkcji skrótu w bardziej zwięzłym języku, aby zrobić krótsze rozwiązanie.

Alexander Hanysz
źródło