Шахматный эндшпиль: Белое, чтобы спариться в одном

19

Учитывая сетку букв 8x8, представляющую текущее состояние игры в шахматы, задача вашей программы состоит в том, чтобы найти следующий ход для белых, который приводит к мату (ответ всегда будет матом за один ход).

вход

Ввод будет осуществляться через STDIN - 8 строк по 8 символов в каждой. Значения каждого символа следующие:

K/k - king
Q/q - queen
B/b - bishop
N/n - knight
R/r - rook
P/p - pawn
- - empty square

Буквы в верхнем регистре обозначают белые части, а строчные - в черном. Доска будет ориентирована так, чтобы белые играли снизу вверх, а черные сверху вниз.

Выход

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

Пример ввода

Пример 1

Входные данные:

------R-
--p-kp-p
-----n--
--PPK---
p----P-r
B-------
--------
--------

Выход:

c6

Пример 2

Входные данные:

--b-r--r
ppq-kp-p
-np-pn-B
--------
---N----
--P----P
PP---PP-
R--QRBK-

Выход:

Nf5

Пример 3

Входные данные:

---r-nr-
-pqb-p-k
pn--p-p-
R-------
--------
-P-B-N-P
-BP--PP-
---QR-K-

Выход:

Rh5

Вы можете предположить, что решение не будет включать рокировку или проход.

Это код-гольф - выигрывает самое короткое решение.

(Примеры взяты с сайта mateinone.com - пазлы 81, 82 и 83)

Gareth
источник
Нет. Я думаю, что для целей этого вопроса вы можете предположить, что ответ не будет касаться рокировки или участия. Я обновлю вопрос.
Гарет
Как мы должны обрабатывать позиции с более чем одним помощником?
Роб
@Rob Требуется только одно решение, поэтому выведите любое решение, которое вы найдете первым.
Гарет
Также безопасно предположить, что решение не связано с продвижением?
Питер Тейлор
@ Питер Да, я не хочу слишком усложнять проблему.
Гарет

Ответы:

7

Ruby, 589 512 510 499 493 символа

R=0..7
a=->b{o=[];R.map{|r|R.map{|c|v=Hash[?K,[6,7,8,11,13,16,17,18],?R,s=[157,161,163,167],?B,t=[156,158,166,168],?Q,s+t,?N,[1,3,5,9,15,19,21,23],?P,[32,181,183]][z=b[r][c]];v&&v.map{|s|k=2!=l=s/25+1;u=r;v=c;l.times{u+=s/5%5-2;v+=s%5-2;R===u&&R===v||break;t=b[u][v];j=t<?.&&l<8;(j||t=~/[a-z]/&&k)&&o<<=(h=b.map &:swapcase;h[u][v]=h[r][c];h[r][c]=?-;[z+"%c%d"%[97+v,8-u],h.reverse]);j&&(k||r==6)||break}}}};o}
a[$<.map{|l|l}].map{|m,b|a[b].any?{|f,x|a[x].all?{|g,y|y*""=~/K/}}||$><<m[/[^P]+/]}

Ввод осуществляется через стандартный ввод, например:

> ruby mateinone.rb
--------
--------
--------
-k------
b-------
-N-P----
--------
-----K-Q
^Z
Qb7

Результатом является не только один ход, который заставляет партнера в одном, но каждый ход, который делает это.

Редактировать 1: функция eиспользовалась только один раз, поэтому я добавил ее. Во-вторых, кодировка теперь основана на числе 5, а не 10. И рефакторинг клонирования доски сэкономил немало символов.

Редактировать 2: Все еще не так много улучшений, как я хотел. Меняем хеш с {a=>b,c=>d}на Hash[a,b,c,d]. Это стоит 4 символа, но сохраняет один на пару ключ-значение.

Правка 3: Только незначительные сокращения: встраивание M (4 символа), t==?--> t<?.(2), удаление Pawn в алгебраической нотации в конце (2), замененные путы (3). В программе сейчас менее 500 символов.

Редактировать 4: Интересно, сколько еще можно найти в такой программе. Переместил инвариант за пределы цикла и нашел еще один дубликат вычисления.

Говард
источник
Под "не один, а любой" вы подразумеваете "не обязательно один, но каждый"?
Мэтью Прочитал
@ Мэтью Ты прав. Я имел в виду "каждый".
Говард
Вы можете использовать [*$<]вместо $<.map{|l|l}.
Lowjacker