Haskell - 迭代和填充列表

时间:2018-04-08 02:48:30

标签: list loops 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]

  3. 数字2中最终列表的大小为20,这是我想要返回的值

    说到这里,我有关于如何实现这个实现的想法。我实施此计划的计划是:

    1. 使用多个数字的值填充单个列表 小于等于收到的第一个号码。
    2. 获取已填充的列表,然后对其进行分组。
    3. 取组的长度,然后 打印价值。
    4. 要开始,我已完成以下操作以阅读所有输入,存储到列表中并将其传递给函数进行打印以确认我已收到正确的值:

      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
      

      此时,我被困住了。

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

      对此有何帮助?

1 个答案:

答案 0 :(得分:0)

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

  1. 查找2和n
  2. 之间的所有两个倍数
  3. mm
  4. 之间查找n的所有倍数
  5. 将两个列表排序在一起,删除重复项
  6. 获取结果列表的长度并将其打印
  7. 步骤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