Haskell - Iterate and Populate list
我对Haskell还是很陌生,这是迄今为止我发现的最难缠的语言。我在网上找到了一篇过往的论文,因此决定尝试在haskell中进行实践。
我的myFile.txt中有一个整数列表,如下所示:
1 2 3 4 5 6 | 5 3 30 10 120 80 96 95 96 98 98 |
列表中第一个数字的整数是告诉我接下来要进行的测试次数。在这种情况下,将跟随5。
我正在尝试为每个测试(例如3 30)返回一个数字(例如:20),以表示特定范围内的总倍数。
第一个测试的示例为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,这就是我要返回的值。
话虽如此,我对如何执行此实现有想法。我执行此实现的计划是:
小于并等于收到的第一个数字。
打印值。
首先,我已完成以下操作以读取所有输入,将其存储到列表中并将其传递给函数以进行打印,以确认我已收到正确的值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
这时,我被卡住了。
我试图弄清楚如何迭代列表的值,并使用这些值以其倍数填充另一个列表,如上文所述。
对此有任何帮助吗?
所以这有几个部分,如果将??它们分解成每一步,那么每个步骤都非常简单。每行的输入为
第1步和第2步在同一函数中处理:
1 | multiplesOfN n = [n, n+n..] |
这将建立一个无数的倍数值列表。应用
这时,您需要将两个列表合并在一起,删除重复项。由于它们都是升序列表,因此只需一步合并排序即可轻松实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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 |
获得结果列表的长度仅为
1 2 3 4 5 6 7 8 9 10 | 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 |