我有一个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 ......
感谢您的思考
答案 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]