我对哈斯克尔来说很新,而且这是迄今为止我发现的最困难的语言。我在网上发现了一篇过去的论文,我决定尝试在haskell中实现这一点。
我有一个像myFile.txt中的以下整数列表:
5
3 30
10 120
80 96
95 96
98 98
列表中的第一个数字有一个整数,告诉我将跟随多少次测试。在这种情况下,将跟随5。
我试图为每个测试返回一个数字(例如:20)(例如:3 30),表示特定范围内的总倍数。
作为第一次测试的一个例子,3 30:
我需要找到每个数字的倍数,从2到第一个数字(在本例中为2和3),最多值为30.在这种情况下:
2的倍数:[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30]
3的倍数:[3,6,9,12,15,18,21,24,27,30]
然后我找到相似之处然后计算所有唯一值:
[2,3,4,6,8,9,10,12,14,15,16,18,20,21,22,24,26,27,28,30]
数字2中最终列表的大小为20,这是我想要返回的值
说到这里,我有关于如何实现这个实现的想法。我实施此计划的计划是:
要开始,我已完成以下操作以阅读所有输入,存储到列表中并将其传递给函数进行打印以确认我已收到正确的值:
main = do
let myList = []
handle <- openFile "myFile.txt" ReadMode
contents <- hGetContents handle
let singlewords = words contents
myList = f singlewords
printMyVals myList
hClose handle
f :: [String] -> [Integer]
f = map read
printMyVals :: [Integer] -> IO()
printMyVals myList =
print myList
此时,我被困住了。
我试图找出如何迭代我的列表的值,并使用这些值用它的倍数填充另一个列表,如上所述。
对此有何帮助?
答案 0 :(得分:0)
所以这里有一些部分,如果你将它们分解为每个步骤,每个步骤都相当简单。每行的输入为m
和n
:
n
m
和m
n
的所有倍数
步骤1和2在同一个功能中处理:
multiplesOfN n = [n, n+n..]
这将构建一个无限的倍数值列表。应用takeWhile (<=x)
以获取上限值。对于输入的第一行,您将拥有:
twos = takeWhile (<=30) . multiplesOfN $ 2
threes = takeWhile (<=30) . multiplesOfN $ 3
然后你需要将两个列表合并在一起,删除重复项。由于它们都是升序列表,因此在一步合并中很容易做到。
mergesort :: (Eq a, Ord a) => [a] -> [a] -> [a]
mergesort [] ys = ys
mergesort xs [] = xs
mergesort xss@(x:xs) yss@(y:ys)
| x < y = x : mergesort xs yss
| otherwise = y : mergesort xss ys
-- but this doesn't remove duplicates! Let's deal with that by
-- adding a new argument @lastValue@ and discarding if any match
uniqMergesort :: (Eq a, Ord a) => [a] -> [a] -> [a]
uniqMergesort xs [] = xs
uniqMergesort [] ys = ys
uniqMergesort xss@(x:xs) yss@(y:ys)
| x < y = x : go x xs yss
| otherwise = y : go y xss ys
where
go _ [] [] = []
go lastValue (x:xs) []
| lastValue == x = go lastValue xs []
| otherwise = x : go lastValue xs []
go lastValue [] (y:ys)
| lastValue == y = go lastValue [] ys
| otherwise = y : go lastValue [] ys
go lastValue xss@(x:xs) yss@(y:ys)
| x < y = if x == lastValue
then go lastValue xs yss
else x : go x xs yss
| otherwise = if y == lastValue
then go lastValue xss ys
else y : go y xss ys
获得结果列表的长度只是length
,从文件中提取值将分为行,然后是单词,然后读取每个单词。
main :: IO ()
main = do
handle <- openFile "myFile.txt" ReadMode
contents <- hGetContents handle
let inputs = map (map read . words) . lines $ tail contents
results = [let xs = takeWhile (<=n) . multiplesOfN $ 2
ys = takeWhile (<=n) . multiplesOfN $ m
in uniqMergesort xs ys | [m, n] <- inputs]
mapM_ (print . length) results
hClose handle