总结排列列表的距离(Haskell)

时间:2013-11-20 11:34:12

标签: haskell haskell-mode

我有一个Towns和一个函数列表,它给出了两个之间的距离。例如:

dist!(Bielefeld,Muenchen) = 598

现在我想创建一个函数,我可以计算所有城镇之间随机游览的全长。例如:

tourlength [a permutation of the 12 Towns] = whole way you have to travel (as Int)

我希望你知道我的意思。我不确定如何将dist!函数集成到新函数中。

我的第二个问题是我想计算哪个城市到第二个城市的距离最短。为了解决这个问题,我想使用下面的greedy函数:

greedy a []     = [a]
greedy a X      = a : greedy (z X - [z])
              z = argmin x : dist a x 
tspgreedy X     = greedy (s x - [s])

但我不知道如何翻译成haskell ......

感谢您的思考

1 个答案:

答案 0 :(得分:2)

在回答你的第一个问题时,计算通过一系列城镇的旅程的总距离的一种方法是这样的:

import Data.Complex (Complex, magnitude)

type Town = Complex Double

dist :: Town -> Town -> Int
dist x y = round $ magnitude (x-y)

journeyDistance :: [Town] -> Int
journeyDistance itinerary = sum . zipWith dist itinerary . drop 1 . cycle $ itinerary

(不要因使用复杂的数字而拖延;你可以通过查表来定义你的城镇和他们之间的距离,比如你喜欢的。)这段代码背后的想法是压缩列表代表行程与自身 - 但由一个城镇抵消(因此drop 1) - 计算拉链时的距离。也就是说,我们将每个城镇与其行程中的继任者配对,但配对操作不是通常的元组构造,而是我们自己的距离函数(因​​此zipWith dist)。 cycle构建了无限重复的行程,以确保有足够的城镇与原始的有限城镇列表“完全拉链”。

事实上,因为zip中的第二个列表“循环”,所以第一个列表中的最后一个城镇将与第一个城镇配对,形成往返。如果您宁愿在最后一个城镇结束旅程而不返回第一个城镇,那么您可以编写如下函数:

journeyDistance itinerary = sum . init . zipWith dist itinerary . drop 1 . cycle $ itinerary

解决第二个问题的快速方法可能是这样的:

import Data.List (minimumBy, tails)
import Data.Ord (comparing)

closestTowns :: [Town] -> (Town, Town)
closestTowns towns = minimumBy (comparing $ uncurry dist) [(x, y) | (x:xs) <- tails towns, y <- xs]