【问题标题】:Prime Factoring Function in HaskellHaskell中的素数分解函数
【发布时间】:2014-11-10 20:48:45
【问题描述】:

我正在尝试创建一个函数,该函数将显示一个数字的主要因素以及我给它的列表(无限)。这是我目前所拥有的:

-- Here is a much more efficient (but harder to understand) version of primes.
-- Try "take 100 primes" as an example (or even more if you like)
primes = 2 : primesFrom3 where 
    primesFrom3 = sieve [3,5..] 9 primesFrom3
    sieve (x:xs) b ~ps@(p:q:_)
      | x < b     = x : sieve xs b ps
      | otherwise =     sieve [x | x <- xs, rem x p /= 0] (q^2) (tail ps)



-- Write a function that factors its first argument using the (infinite)
-- list of available factors given in its second argument
-- (using rem x p /= 0 to check divisibility)
primeFactsWith :: Integer -> [Integer] -> [Integer]
primeFactsWith n (p:ps) = if (rem n p /= 0) then
                                (primeFactsWith n ps)
                          else (primeFactsWith p ps)

上半部分不是我写的,效果很好。我试图让下半场工作,但事实并非如此。阅读代码中的 cmets 以更好地了解我想要做什么。谢谢!哦,请不要只是说出答案。给我一些关于如何做的提示,也许是什么问题。

【问题讨论】:

  • 您也可以尝试primes = 2 : 3 : sieve [5,7..] 9 primesFrom3 where ... 并比较main = print (primes !! n) 中增加ns 的内存使用率(以及时间)。将其作为独立可执行文件运行($&gt; primes +RTS -s 以查看统计信息),使用优化开关 -O2 编译。

标签: haskell primes prime-factoring


【解决方案1】:

怎么了

问题是你在两个分支中都进行了递归调用,因此函数永远不会停止。

一些提示

要构建递归列表生成函数,您需要两个分支或案例:

  • 基本情况没有递归调用,这将停止递归并返回结果的最后部分。
  • 递归案例在这里你修改函数的参数,并用修改后的参数再次调用它,可能还会返回部分结果。

递归分支需要两个子分支。一个如果你找到了一个素因数,另一个如果当前数字不是素因数。

这里是一个骨架,需要填写&lt;&gt;括号内的部分。

primeFactsWith :: Integer -> [Integer] -> [Integer]
primeFactsWith n (p:ps) = if <halt condition> then
                            <final result>
                          else if (rem n p /= 0) then
                            <not a factor - recursive call 1>
                          else 
                            <found a factor - return it, 
                             and make recursive call 2>
  • 如果你找到了一个素因数,你可以用这个数除以它,得到一个更小的数,没有那个因数。为了执行整数除法,Haskell 提供了一个名为 div 的函数。

  • 如果你达到了数字 1,你已经产生了所有的质因数,你可以停下来。质因数列表的最后一部分,在其所有因数之后,是一个空列表。

  • 如果不再需要,您可以从无限列表中删除任何素数,但请注意,一个数可能在因子列表中多次包含素数。如果你想删除p,你可以使用模式中的ps;如果你想保留p,你必须使用(p:ps)

  • cons 运算符(:) 可用于构建列表。您可以使用它返回结果列表中的一个数字,并使用递归调用来查找剩余的数字,例如

    x : foo y z

希望对你有所帮助,如果有任何问题,请不要犹豫。

【讨论】:

  • “p 是一个整数,但 n 是一个整数列表”。不,根据primeFactsWith :: Integer -&gt; [Integer] -&gt; [Integer],在primeFactsWith n (p:ps) 中,nIntegerpIntegerps[Integer]
  • “您尝试将 p 作为参数传递给它期望 [Integer] 的 primeFactors”。 OP 确实将p 作为参数传递给primeFactsWith,但在第一个位置。它期望 Integer 的位置,p 是。
  • 我好像错过了阅读OP的功能。关于类型不匹配的部分,是废话,我将其删除。我的其余答案不应受此影响。
【解决方案2】:

这里有一个提示。

所以你在递归,这很好。

在一个分支中,您一直在寻找n 的因子。在另一个分支中,您似乎在寻找p 的因子,这有点奇怪,但whatevs。

你找到的n的因子在哪里返回?

【讨论】:

    猜你喜欢
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    • 2013-02-08
    • 2023-03-12
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多