Расскажи мне ходы

28

Джек и Джейн решили поиграть в шахматы, чтобы скоротать время. К сожалению, Джек плохо умеет визуализировать. Он считает, что трудно определить возможные ходы для данной фигуры, кроме пешки, конечно!

Ваша задача состоит в том, чтобы помочь Джеку найти возможные варианты для данной фигуры (кроме пешки).

Если кто-то забыл, различные части обозначаются как:

  • К: Кинг
  • Q: королева
  • N: рыцарь
  • Б: епископ
  • R: Ладья

В качестве примера, на следующем изображении конь расположен на d4и может перейти к c2, b3, b5, c6, e6, f5, f3, e2. Для данного входа:

Nd4

вы бы произвели:

Nc2 Nb3 Nb5 Nc6 Ne6 Nf5 Nf3 Ne2

введите описание изображения здесь

Правила:

  • Порядок вывода не имеет значения, если перечислены все возможные ходы
  • Возможные шаги могут быть разделены пробелами, символами новой строки или любым другим разделителем
  • Ввод может быть передан в программу в качестве параметра или через STDIN
  • Пробелы в программе должны учитываться, поэтому используйте их оптимально

Это код гольф. (Пожалуйста, избегайте использования каких-либо инструментов / утилит, специально предназначенных для этой цели.) Самый короткий ответ выигрывает!

devnull
источник
1
Я считаю, что это будет прекрасно работать в качестве кода гольфа
Джон Дворак
3
Код гольф является лучшим выбором. Очевидное всегда забывается: я понимаю, что мы можем передать либо функцию, либо программу, и что ввод / вывод может быть либо stdin / stout, либо параметры / возвращаемое значение. Я думаю, что рекурсия может быть полезна здесь для королевы: f(x)... case "Q": {f("B");f("R")}если функция требует какой-либо #include, они должны быть частью числа байтов.
Уровень Река St
4
Шрифт в этом графике. xD
cjfaure
1
Должны ли возможные ходы быть разделены пробелами или символы новой строки тоже в порядке?
Деннис
1
законные ходы для пешки более запутанны, чем любая другая фигура (en passant, захват по диагонали и начальный ход в 2 квадрата). так что я полагаю, Джек также запомнил правила рокировки?
ardnew

Ответы:

7

GolfScript, 94 93 символа

Моя первая в мире программа GolfScript! Это заняло у меня много часов бездельничания, не зная, что я делаю, но я упорствовал и думаю, что сумел выучить основы языка и довольно хорошо его освоить.

Полностью в гольф :

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

Прокомментированный и более хороший источник :

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

Это может выглядеть как ответ Клаудиу, потому что я ссылался на его ответ, а также на мое (не представленное) решение C, пока принимал мой. Он предоставил хороший образец (относительно) сложной, работающей программы GolfScript, и это помогло мне многое узнать о языке. Так что спасибо, Клавдиу!

Будучи новичком в GolfScript, если у вас, ребята, есть какие-либо отзывы, я был бы рад услышать это!

Runer112
источник
Потрясающе! Хорошая работа =). Позже мне нужно будет внимательнее взглянуть на это, чтобы увидеть, что у вас на 40 символов меньше моего. Разве Гольфскрипт не веселый?
Клаудиу
12

Python, 217 212 220 217 213 символов

Связал 213-байтовое решение 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)

Я начал с генерации всех правильных ходов, но они стали слишком большими, поэтому подход очень похож на подход 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
Клаудиу
источник
Хорошее извлечение строковых символов с этим аргументом кортеж. Жаль, что это больше не работает в Python 3.
Евпок
10

Mathematica, 278 272 264 260 215 213 символов

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

Безголовая версия:

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

Пример использования:

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

Безгольфовая версия создает полный пансион, а затем выбирает правильные позиции с помощью Cases, тогда как гольфовая версия немедленно сбрасывает недействительные ходы в Tableкоманде, выдавая ##&[], что просто исчезает.

Мартин Эндер
источник
Просто любопытно о входе, не так ли N4d? Не должно ли быть Nd4вместо этого?
Devnull
@ уверен, это опечатка. должно быть Nd4.
Мартин Эндер
Выучил известную функцию сегодняChessboardDistance
swish
Согласно документации Mathematica / Wolfram Language, «ChessboardDistance [u, v] эквивалентна Max [Abs [uv]]». Возможно, вы можете сохранить символы, используя последнюю форму, особенно если вы замените Abs [uv] на | uv |.
Майкл Стерн
@MichaelStern это именно то, что я делаю в версии для гольфа;). И, к сожалению, вертикальные черты не работают Absв Mathematica, потому что они обозначают альтернативы в шаблоне.
Мартин Эндер
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]]

Будет сложно потрогать Mathematica, когда в него встроены шахматные ходы: rollseyes: (хорошо играл m.buettner) Я забираю все это обратно. Обыграв Математику на 31!

Последнее редактирование: заменен регистр с функцией, встроенный фильтр в понимание, чтобы превзойти запись в R;)

использование:

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

Ungolfed (соответствует версии 208 символов до того, как '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
источник
Можете ли вы опубликовать версию без гольфа? (если есть, конечно)
swish
@ У меня нет, но я не против написать это.
Bazzargh
@ Готово Надеюсь, что это имеет больше смысла. Спросите, если вам нужно что-то прояснить.
Bazzargh
Отличная работа! Зачем вам нужно добавлять pieceв список, [piece,newfile, newrank]если вы не используете его в сопоставлении с образцом, можете сэкономить некоторые символы?
swish
Это там для вывода. Вы увидите, что я не сопоставляю шаблон с этим в «... каждом возможном движении ...». Первоначально у меня этого не было - шахматные ходы не требуют этого - но потом я заметил, что вопрос хотел этого, и все остальные сделали это, так что это справедливо.
Bazzargh
8

Баш, 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]$'

Как это работает

  • Идея состоит в том, чтобы представлять каждое поле на доске числовым значением, принимая его координаты в качестве числа base-20 и вычитая 200. Таким образом, a1становится 20 * 10 + 1 - 200 = 1, h8становится 20 * 17 + 8 - 200 = 148и т. Д.

    Теперь возможные ходы епископа могут быть представлены (положительные или отрицательные) кратные 19 - одинаковое количество шагов вверх (+20) и влево (-1) - или 21 - такое же количество шагов вверх (+20 ) и направо (+1).

    Размещение фигуры после перемещения - это просто сумма ее первоначальной позиции и движения. После добавления этих чисел мы должны проверить, соответствует ли их сумма действительному полю на доске.

    Поскольку основание (20) более чем в два раза больше максимально возможного числа (8), сумма не может обернуться вокруг доски, например, перемещение Bh1 на семь шагов вправо и вверх приведет к неправильному положению доски.

  • Линия

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

    хранит идентификатор куска в переменной a , числовое представление исходной позиции в b и буквы от a до h в массиве d .

    После расширения скобки eval{,} echo '$'$aстановится eval eval echo '$'$a(вдвойне зло), который оценивает, например eval echo $K, который оценивает echo 1 19 20 21.

  • for i in $c -${c// / -};do …; done циклы над всеми возможными движениями и их негативными аналогами.

  • echo $a${d[$[(i+=b)/20]]}$[i%20] дает окончательную позицию после движения.

  • grep '[a-h][1-8]$' удостоверяется, что у нас есть правильная позиция

Деннис
источник
7

Golfscript, 144 135 знаков

Вместо того, чтобы продолжать пытаться поиграть в свое решение Python , я перевел его на 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}/;;}/

Простой перевод без особой игры в гольф, так что, скорее всего, его можно будет убрать дальше. Принимает ввод из стандартного ввода без перевода строки, попробуйте здесь (первые две строки для имитации стандартного ввода).

Клаудиу
источник
Кажется, работает хорошо! Я надеюсь, что кто-то тоже придумает решение brainf * ck.
devnull
6

C 634 632 629 625 600 символов

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

Любые предложения о том, как улучшить это? Я впервые отправляю ответ.

calccrypto
источник
Добро пожаловать в Code Golf! Для начала вы можете удалить пробелы в вашем коде. Помните, что это кодовый гольф, который подразумевает, что выигрывает самый короткий код. Поэтому попытайтесь уменьшить размер вашей программы.
devnull
Не забудьте обновить количество символов тоже!
Devnull
@devnull нужны ли пробелы?
Calccrypto
1
Еще одна вещь: Cможет быть значительно упрощена с помощью троичного оператора ?:и с помощью возвращаемого значения printf. ( printfвозвращает количество написанных символов, поэтому в этом случае оно всегда ненулевое.) C(P,c,r){return(0<=c)&(c<8)&(0<r)&(r<9)?printf("%c%c%d ",P,c+'a',r):0;}. Незначительные изменения: есть дополнительное пространство Mпосле того , ifчто вы можете удалить.
user12205
1
Прямо сейчас вы, кажется, не считаете никаких новых строк. Хотя некоторые из них могут быть удалены, другие не могут. Обязательные символы новой строки должны определенно способствовать подсчету байтов.
Деннис
3

Haskell, 300 269 ​​символов

Спасибо bazzargh за помощь в потере 31 персонажа ...

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}

Тот же алгоритм, что и в версии Mathematica. Пример вывода из ghci:

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

(Вы не просили проверки работоспособности!)

Александр Ганыш
источник
Вы можете избавиться от синтаксических пробелов. Смотрите мой ответ здесь: codegolf.stackexchange.com/questions/19255/… (точнее, вы хотите let {h = d (x !! 1) (y !! 1); ...})
bazzargh
1

Haskell, 446 символов

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)

Вызывается с помощью jфункции

j "Nd4"

Я не работал с Haskell в течение нескольких месяцев, поэтому он не оказался таким же коротким, как большинство других решений, но я уверен, что есть некоторые оптимизации, в основном с h. Я мог бы сократить это немного.

Сильвио Майоло
источник
1

Q & K [ 311 262 символов]

Существует потенциальная возможность уменьшить количество персонажей. Я буду уменьшать его в следующей итерации.

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}

использование

ладья

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

король

g"ka1"
`a2`b1`b2

рыцарь

g"na1"
`b3`c2

епископ

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

Королева

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 символа

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

Безголовая версия:

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

Использование:

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

Решение даже хорошо читаемое. Однако я добавил несколько скобок и комментариев для читателей, незнакомых с кодом R (в версии без заглавных букв).

lambruscoAcido
источник
0

Haskell (гипотетический), 248 символов

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

К сожалению, у каждого компилятора Haskell, который я могу получить прямо сейчас, есть проблемы со строковыми литералами Unicode. Вот (более длинная) версия, которая действительно работает:

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"

Определение h x y=...является хеш-функцией; допустимые ходы будут хэшировать номера символов, которые находятся в 41-символьной строке. Это избавляет от необходимости использования оператора case или его эквивалента.

Я не планирую работать над этим прямо сейчас. Было бы интересно посмотреть, может ли кто-нибудь использовать хеш-функцию на более лаконичном языке, чтобы сделать более короткое решение.

Александр Ганыш
источник