我有一个文件(points.txt),其中定义了一些笛卡尔坐标:
A 1.0 2.2
B 2.1 3.0
C 3.5 4.0
D 4.0 5.0
我有第二个文件(routes.txt),其路线是根据points.txt中的点定义的。
route1 ACDB
route2 ABC
我需要找到每条路线的长度。到目前为止,我计算了两点之间的距离,如下所示:
type Point = (String, Float, Float)
distance_points :: IO ()
distance_points = do s <- readFile "pontos.txt"
putStr "Fom: "
p1 <- getLine
putStr "To: "
p2 <- getLine
print ( distance (search_point p1 (map words (lines s))) (search_point p2 (map words (lines s))))
search_point :: String -> [[String]] -> Point
search_point pt ([p,c1,c2]:xs) = if pt == p then (p, read(c1)::Float, read(c2)::Float)
else search_point pt xs
distance :: Point -> Point -> Float
distance (s1,x1,y1) (s2,x2,y2) = sqrt ((x1-x2)^2 + (y1-y2)^2)
如何计算路线的全程?
另外,如果我有几条路线,我怎样才能找到最长的路线?
提前致谢。
答案 0 :(得分:8)
最简单的方法是先用纯代码解决问题,然后再添加文件读取。否则你会想要编写很多IO代码。
如果将名称与坐标分开,将会更容易:
type Coordinates = (Float,Float)
type Name = Char -- You had String, which is also fine
type Point = (Name, Coordinates)
type Points = [Point] -- or Map String Point from Data.Map
然后有一些练习数据:
sampleData :: Points
sampleData = [('A',(1.0,2.2), .....
首先,你需要一个带名字的函数,并为你提供一些坐标。
coordinates :: Points -> Name -> Coordinates
如果我们使用[Point]
,最简单的方法是使用lookup
。 (你可以在hoogle like this或类型like this上找到相关功能,但是没有明显的方法让你知道你想要Maybe
,当你只是搜索{{ 1}},查找还有很长的路要走。)
如果您需要有关此步骤的帮助,请发表评论。
使用它你就可以写
[(a,b)] -> b
distBetween :: Points -> Name -> Name -> Float
或(冷静)使用getPath :: String -> [(Name,Name)]
来达到距离。之后,应用zipWith
应该很容易解决问题。
制作这个对列表的一个很酷的方法是使用我们用于使用其尾部压缩函数的斐波纳契数(sum
)的技巧。如果您没有遇到它,zip的工作原理如下:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
太棒了 - 这正是你需要的技巧。
你需要像
这样的功能 ghci> zip [1..5] "Hello Mum"
[(1,'H'),(2,'e'),(3,'l'),(4,'l'),(5,'o')]
zip "Hello" "ello"
[('H','e'),('e','l'),('l','l'),('l','o')]
*Main> zip "Hello" (tail "Hello")
[('H','e'),('e','l'),('l','l'),('l','o')]
然后你可以将它粘在一起,例如:
readPointsFile :: FilePath -> IO Points
readPointsFile fileName = do
....
....
return (map readPoint pointStrings)
注意这个位中几乎没有任何逻辑。你可以用纯粹的代码完成所有真正的移植。
暗地里我是一个庞大的pathLengthFile :: FilePath -> FilePath -> IO Float
pathLengthFile pointsFilename pathFilename = do
points <- readPointsFile pointsFilename
path <- readPathFile pathFilename
return (getPathLength points path)
粉丝,想要Applicative
并将其写成
import Control.Applicative
但这是后来的另一个教训。 :)