Нахождение кратчайшего пути между двумя точками на сетке, используя Haskell - PullRequest
10 голосов
/ 16 марта 2010

Это проблема, которую я могу достаточно легко решить нефункциональным образом.

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

Проблема:

У меня есть 2D-поле, разделенное на прямоугольники одинакового размера. Простая сетка. Некоторые прямоугольники являются пустым пространством (и могут быть пропущены), в то время как другие непроходимы. Учитывая начальный прямоугольник A и целевой прямоугольник B , как рассчитать кратчайший путь между ними? Движение возможно только по вертикали и по горизонтали, с шагом в один большой прямоугольник.

Как мне поступить, выполняя это в Хаскеле? Фрагменты кода, безусловно, приветствуются, но также не обязательно. И ссылки на дальнейшие ресурсы также очень приветствуются!

Спасибо!

Ответы [ 2 ]

12 голосов
/ 16 марта 2010

Я бы представлял сетку в виде списка списков, введите [[Bool]]. И я бы определил функцию, чтобы знать, заполнен ли элемент сетки:

type Grid = [[Bool]]
isFullAt :: Grid -> (Int, Int) -> Bool  -- returns True for anything off-grid

Тогда я бы определил функцию для поиска соседей:

neighbors :: (Int, Int) -> [(Int, Int)]

Чтобы найти неполных соседей по point, вы можете отфильтровать с помощью filter (not . isFullAt) $ neighbors point.

На этом этапе я бы определил две структуры данных:

  • Отобразить каждую точку на Maybe Cost
  • Храните все очки с известной стоимостью в куче

Инициализировать только с начальным квадратом A в куче, с нулевой стоимостью.

Затем выполните цикл следующим образом:

  • Удалите квадрат минимальной стоимости из кучи.
  • Если его еще нет на конечной карте, добавьте его и его стоимость c и добавьте в кучу всех неполных соседей со стоимостью c+1.

Когда куча пуста, вы будете иметь стоимость всех достижимых точек и можете посмотреть B на конечной карте. (Этот алгоритм можно назвать «алгоритмом Дейкстры»; я забыл.)

Вы можете найти конечные карты в Data.Map. Я предполагаю, что где-то в огромной библиотеке есть куча (приоритетная очередь), но я не знаю, где.

Надеюсь, этого достаточно, чтобы вы начали.

3 голосов
/ 16 марта 2010

Ну, ваши типы будут определять ваши алгоритмы.

Какой тип данных вы хотите использовать для представления сетки? Двумерный массив? Список списков? Дерево? График?

Если вы просто хотите кратчайший путь в ориентированном графе, лучше использовать что-то из FGL (пакет функциональных графов).

...