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


28

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

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

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

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

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

Nd4

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

Nc2 Nb3 Nb5 Nc6 Ne6 Nf5 Nf3 Ne2

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

Правила:

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

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


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, если у вас, ребята, есть какие-либо отзывы, я был бы рад услышать это!


Потрясающе! Хорошая работа =). Позже мне нужно будет внимательнее взглянуть на это, чтобы увидеть, что у вас на 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.

Можете ли вы опубликовать версию без гольфа? (если есть, конечно)
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}}

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


Добро пожаловать в 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 (в версии без заглавных букв).


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 или его эквивалента.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.