Haskell - 迭代和填充列表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Haskell - 迭代和填充列表相关的知识,希望对你有一定的参考价值。

我是哈斯克尔的新手,这是迄今为止我发现的最困难的语言。我在网上发现了一篇过去的论文,我决定尝试在haskell中实现这一点。

我有一个像myFile.txt中的以下整数列表:

5
3 30
10 120
80 96
95 96
98 98

列表中的第一个数字有一个整数,告诉我将跟随多少次测试。在这种情况下,将跟随5。

我试图为每个测试返回一个数字(例如:20)(例如:3 30),表示特定范围内的总倍数。

作为第一次测试的例子,3 30:

  1. 我需要找到从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. 然后我找到相似之处然后计算所有唯一值: [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. 取组的长度,然后打印该值。

要开始,我已完成以下操作以读取所有输入,存储到列表中并将其传递给函数以打印它以确认我已收到正确的值:

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

此时,我被卡住了。

我试图弄清楚如何迭代我的列表的值,并使用这些值填充另一个列表与它的倍数,如上所述。

对此有何帮助?

答案

所以这里有几个部分,如果你将它们分解为每个步骤,每个步骤都相当简单。每行的输入是mn

  1. 找到2和n之间的所有两个倍数
  2. mm之间找到所有的n倍数
  3. 将两个列表排序在一起,删除重复项
  4. 获取结果列表的长度并打印出来

步骤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

以上是关于Haskell - 迭代和填充列表的主要内容,如果未能解决你的问题,请参考以下文章

如何在片段中填充列表视图?

使用 json rereiver php mysql 在片段中填充列表视图

Haskell 需要帮助理解流

Android - 使用片段和简单的光标适配器填充列表视图

如何在迭代另一个列表时填充新列表?

如何在UL中迭代使用appendChild和片段LI?