【问题标题】:Create infinite list in Haskell of k-composite numbers在 Haskell 中创建 k 复合数的无限列表
【发布时间】:2018-03-07 05:23:26
【问题描述】:

k-合数是除 1 和自身之外的 k 个因数的合数。我正在尝试编写将接受整数 k 并返回所有 k 复合材料的无限列表的代码。所以使用 take 5 $ kcomposite 2 将返回 [6,8,10,14,15]。我写了两个函数来完成这个:

factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]

kcomposite ::  Int -> [Int]
kcomposite n = [x | x <- [1..], (length (factors n)) == (x-2)]

我编译没有问题,但是当我尝试运行它们时,ghci 永远不会停止运行。这是有道理的,因为无限列表,但即使我只尝试获取列表中的前几个元素,也会发生这种情况,就像上面的例子一样。我不明白我做错了什么。

【问题讨论】:

  • 看起来你切换了 x 和 n。你需要(length (factors x)) == n-2
  • 当然也是 n+2,而不是 n-2。

标签: list function haskell


【解决方案1】:

k-合数是除1和自身之外的k个因数的合数

由于您的factors 函数返回一个数字的所有因数(包括1 和它本身),这个数字将大于提供的k。这就是为什么你需要与k + 2而不是k - 2进行比较

另外,当k 小于0 时,您仍然可以让程序永不停止运行,这就是您可能想要处理这种边缘情况的原因。

factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]

kcomposite ::  Int -> [Int]
kcomposite k
  | k < 0 = []
  | otherwise = [x | x <- [1..], length (factors x) == (k + 2)]

【讨论】:

    【解决方案2】:

    这是我对这项任务的稍微不同的方法,它更有效。

    提升的关键是一直检查到最后,而只检查到它的平方根。我的意思是,如果我们想找到 100 的复合数,我们不需要控制所有 100 个数字。我们只需要控制到sqrt 100(如[2..10])就可以看到(mod 100 x) == 0。我们从 2 开始,因为您不想要 1 和数字本身。一旦我们得到满意的数字100 div x 应该给我们另一个。因此,如果 2 是复合数,那么 100 div 2 (50) 是另一个,例如 4 产生 25,5 产生 20。当然,当我们达到 10 时,它会给我们另外 10 个,我们只会评估其中一个。酷..!

    这就是代码

    kcomposites :: Int -> [Int]
    kcomposites k = 
      let factors n = concat [bool [x, n `div` x] [x] (x^2 == n) 
                              | x <- [2..limit], n `mod` x == 0]
              where limit = truncate . sqrt . realToFrac $ n
      in foldr (\n rs -> bool rs (n:rs) (k == (length . factors $ n))) [] [2..]
    

    这是前 5 个元素在 k = 19 时代码的性能;

    *Main> take 5 . kcomposites $ 19
    [576,1600,2916,3136,7744]
    (0.43 secs, 174,826,272 bytes)
    

    这是您的代码在前 5 个元素的 k = 19 时的性能;

    *Main> take 5 . kcomposite $ 19
    [576,1600,2916,3136,7744]
    (17.61 secs, 6,246,022,504 bytes)
    

    注意:我不建议为 5 个元素检查 k = 5。即使是这段代码也花了大约 15 分钟才能得出[64,729,15625,117649,1771561] 上面的代码可能会花费大量时间(可能需要一天或更长时间)。

    让我们将它们与take 3 进行比较。

    *Main> take 3 . kcomposites $ 5
    [64,729,15625]
    (1.14 secs, 472,228,880 bytes)
    
    *Main> take 3 . kcomposite $ 5
    [64,729,15625]
    (69.84 secs, 25,409,801,688 bytes)
    

    【讨论】:

    • ... 为什么是 5?因为 7 是素数,所以只能通过 n^6 个数得到,即只有 一个 素数的数。
    • @Will Ness 对不起......我不确定你的意思......我们追求的这 5 个因素不是质数,而是最大的因素。有 7 个因素的数字很多,而找到一个有 9 的数字因子似乎比找到一个 5 更难。作为旁注......对于一个具有奇数个因子的数字,它必须有一个完美的整数平方根。
    • 如果一个数有素数因式分解p^a*q^b*r^c*...,它的除数总数是product [a+1,b+1,c+1,...],包括1和它自己。因此,如果它有 5 = 7-2 除数,不包括 1 和它本身,它一定是 product [a+1,b+1,c+1,...] = 7,但 7 是素数,所以该列表中只能有一个条目,product [a+1] = (a+1) = 7 因此 a=6 和素数分解是p^6 一些素数p。 // 对于 7 个因子,不包括 product [a+1,b+1,c+1,...] = 9,例如 3*3 = 9 用于 p^2*q^2 的因式分解,或者也为 p^8。 // 9 = 11-2, 11 是素数,因式分解是p^10
    • 自然10次方比6次方稀疏得多。
    • @Will Ness 谢谢你的解释。我刚刚有时间弄清楚你到底是什么意思。因此,通过该算法查找具有11, 15, 17, 21... (p - 2) 因子的数字将是困难和浪费的。相反,我们最好简单地将逻辑切换到take 5 . map (^(k+1)) $ primes,因为需要如此数量的因子。酷..!
    猜你喜欢
    • 2011-01-03
    • 2014-11-26
    • 2021-03-30
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2014-05-16
    • 2018-01-14
    • 1970-01-01
    相关资源
    最近更新 更多