【问题标题】:haskell beginner - recursive recursionhaskell 初学者 - 递归递归
【发布时间】:2011-07-12 02:57:49
【问题描述】:

刚从 Haskell 开始,我把这个丑陋的部分放在一起来确定一个列表中可以被一个数字整除的数字以及所有小于它的数字。

divis :: (Integral a) => a -> [a] -> [a]
divis _ [] = []
divis n (x:xs)
    | x `mod` n == 0 && n == 2 = x : divis n xs
    | x `mod` n == 0 = divis (n-1) [x] ++ divis n xs
    | otherwise = divis n xs 

我可以这样称呼它......

head (divis 10 [1..])

获取列表中的第一个数字,在本例中为 2520。但是,这似乎不足以使用更高的数字(如 20)有效地解决。

我怎样才能修复这个haskell 的raskell?

【问题讨论】:

  • +1 表示“haskell 的 raskell”
  • 我的第一印象是该算法可能无法提高效率 - 列表中的每个 k 数字直到第一个结果都必须针对所有2 和 n 之间的 n-1 整数,所以这看起来至少是一个二次解。当你考虑到 kn 的关系是超线性的,这看起来像 O(n^3) 左右......
  • 非常感谢您查看,问题开始于我没有通过 [x] 递归或知道如何完成它,但是在我输入我的问题之后,我能够提出它在一起,但是运行它来解决问题需要很长时间,所以我想我还是会问一下,以防我实现了一个糟糕的算法。

标签: haskell recursion functional-programming


【解决方案1】:

这可以通过使用不同的算法来显着改善:可以被一组数字(在本例中为 [1..10])整除的最小数字是这些数字的最小公倍数。

Haskell 甚至内置了一个最不常见的多重函数 (lcm),您可以使用它:

Prelude> foldl lcm 1 [1..10]
2520

如果您不想使用内置的 lcm 函数(因为这几乎是作弊:)),您可以使用 Euclid's algorithm 计算 GCD,然后使用:

lcm a b = a * b `div` gcd a b

如果您需要在给定列表中找到所有可以被 [1..n] 整除的数字,您可以使用任何这样的数字也可以被 [1..n] 的最小公倍数整除的事实]:

divis n xs = filter (\x -> x `mod` mult == 0) xs
    where mult = foldl lcm 1 [1..n]

【讨论】:

  • 瞬时 vs 几分钟,谢谢,还有很多东西要学
  • 比起foldl,更喜欢foldr(当你可以延迟流结构时)或foldl'(当最好的策略是严格评估时)。
猜你喜欢
  • 2016-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多