Вы оказываетесь на шахматной доске, как и каждый. Вы можете видеть выход, но он ужасно далеко, и вы бы предпочли не идти весь путь. К счастью, некоторые местные жители предложили вам прокатиться. Рыцарь, Ладья, Епископ и Король готовы доставить вас к месту назначения, но, видя, что это шахматная доска, они должны соблюдать правила шахмат на пути к месту назначения. Вы хотели бы как можно скорее уйти отсюда, чье предложение вы принимаете?
задача
Учитывая шахматную доску произвольной формы и размера и две точки на шахматной доске, выведите шахматную фигуру, которая может перемещаться между двумя точками за минимальное количество ходов. Доски не обязательно будут непрерывными, что означает, что между разделами доски могут быть промежутки. Каждая из четырех фигур (Король, Ладья, Рыцарь и Епископ) может двигаться в соответствии со своими стандартными правилами в шахматах. Части ферзя и пешки были намеренно исключены из этого испытания.
I / O
Вы можете принимать данные в любом разумном формате, а также в любом формате, который вы выберете. Ваш вход и выход должны быть самосогласованными. Если несколько кусков могут добраться до места назначения за одно и то же количество ходов, вы должны вывести все куски, которые могут добраться за минимальное количество времени. Если ни один из четырех фрагментов не может сделать это до конца, вы можете вывести что-либо, если оно отличается от всех других возможных выходов. Это может включать в себя ничего не выводить или выдавать ошибку.
Тестовые случаи
Квадрат обозначает начальную точку, а кружок обозначает конечную точку.
епископ
рыцарь
король
ладья
Король рыцарь
Никто
Ответы:
Haskell ,
447439437432 байтаВызов с использованием
g <board> <start> <end>
где<board> :: [(Int, Int)]
,<start> :: (Int, Int)
и<end> :: (Int, Int)
. Возвращает список, содержащий1
для Рыцаря,2
Ладьи,3
Епископа и4
Короля. Если решения не найдены, он постоянно переполняет стек (что считается ошибкой, верно?).Вдохновение, взятое из глав LYAH о Монадах
(%)
- это просто обобщение и игра в гольфinMany
, с(&)
эквивалентом(Control.Monad.<=<)
. Все остальное должно быть более или менее самоочевидным.Это, вероятно, может быть гораздо больше, но я уже достаточно повеселился.
Ungolfed:
источник
Mathematica,
326325 байтСпасибо masterX224 за указание экономии байтов!
Определяет функцию,
f
принимающую три аргумента:g
список упорядоченных пар целых чисел, представляющих доску,w
иx
упорядоченные пары, представляющие начальный и конечный квадраты. Выходные данные представляют собой подмножество{b, k, n, r}
(представляющее слона, короля, рыцаря и ладью соответственно), которые имеют путь минимального перемещения между двумя квадратами. Например, третий тестовый пример вызываетсяf[{{0, 0}, {1, 1}, {1, 2}, {0, 3}}, {0, 0}, {0, 3}]
и возвращает{k}
; два последних тестовых случая возвращают{k, n}
и{}
, соответственно.Стратегия состоит в том, чтобы перевести квадраты доски в вершины графа, где края определяются движениями каждого куска, а затем использовать встроенные подпрограммы графа.
Более удобная версия кода:
В строке 3
Select[g~Tuples~2, # - #2 & @@ # == d
находит все упорядоченные пары вершин, разность которых равна векторуd
;e
затем преобразует каждую такую упорядоченную пару в ребро неориентированного графа. Таким образом ,a
это функция , которая создает ребра между всеми вершинами , которые отличаются от фиксированного вектора.Этого достаточно , чтобы определить, в строках 4 и 5, график короля
y@k
(который занимает объединение ребер , порожденных векторами{1, 1}
,{-1, 1}
,{0, 1}
, и{-1, 0}
) и граф рыцаряy@n
(который делает то же самое с{1, 2}
,{2, 1}
,{-2, 1}
и{-1, 2}
).В строке 7
ConnectedComponents@a@#
берет один из этих соседних графов и затем находит его связанные компоненты; это соответствует группированию всех линейных сегментов вершин в заданном направлении (чтобы ладья или слон не проходили через них один за другим). Затемe@t@#
в строке 6 помещаются ребра между каждой парой вершин в одном и том же связанном компоненте, которые затем объединяютсяFlatten
в один граф. Таким образом, строки с 6 по 8 определяют граф ладьи и графy@r
слонаy@b
.Наконец, строки с 9 по 11 выбирают элементы,
{b, k, n, r}
которые дают кратчайший путь между двумя целевыми вершинами.FindShortestPath
выдаст ошибку и вернет неоцененную, если целевая вершина не появится в графе (что произойдет, если из нее не выйдут ребра), поэтому мы используем вместо этогоh@__ -> 0
возврат0
в этих случаях. А отсутствие пути между действительными вершинами возвращает список длины0
, поэтомуMin[z~Complement~{0}]
вычисляет длину наименьшего пути, который существует на самом деле, игнорируя описанные выше плохие случаи.источник
f
сеанс, но я должен был изменить его до представления!