Haskell,了解euler的解决方案#3
我最近学习了一个haskell,并且一直有相当不错的时间。我一直在通过一些Project Euler问题来掌握语法,并一直在回顾这里发布的解决方案http://www.haskell.org/haskellwiki/Euler_problems/1_to_10作为学习工具。虽然我发现自己不能换我的头张贴problem #3解决办法:Haskell,了解euler的解决方案#3
-- Find the largest prime factor of 317584931803.
primes = 2 : filter ((==1) . length . primeFactors) [3,5..]
primeFactors n = factor n primes
where
factor n (p:ps)
| p*p > n = [n]
| n `mod` p == 0 = p : factor (n `div` p) (p:ps)
| otherwise = factor n ps
problem_3 = last (primeFactors 317584931803)
我想不出我的生活是如何工作的。 primes
和primeFactors
似乎在互相呼叫建立自己的名单,并试图遵循它腌我的大脑。任何人都知道关于这个解决方案的好博客文章,或者想在这里写一个关于它的解释?
这确实令人费解一见钟情。但是,如果你不认为“势在必行”,那就没有什么魔力。 Haskell的定义就是这样的:告诉你什么是是,而不是计算机应该执行的更低级别的操作。
因此,素数列表是包含2和所有奇数自然数大于2的列表,它们只有一个素数因子(即它自己)。
另一方面,某个整数n的素因子列表是除n的素数列表。
确保你理解这些定义,阅读之前。作为抽象的Haskell可能,它仍然是一门编程语言,所以我们需要不定期给出一些建议如何计算出一些东西。具体而言,在上面的例子中,我们做不测试的所有质数来找到n
首要因素,因为它是考不上2..k
哪里k*k <= n
。 这也可以确保我们只使用优质的那部分已经被计算。
一开始,primes
看起来是这样的:
2 : filter ((==1) . length . primeFactors) [3,5..]
如果我们2后要求在未来元素,我们强迫的结肠表达正确的评价。这,反过来,会导致过滤器3.然后它去评估谓词:
primeFactors 3
factor 3 (2 : ...)
2*2 > 3
[3]
[3]
因此,primeFactors 3
是[3]
,我们没有需要超越2素数。 (这是关键的一点,为什么这个作品!) 显然,[3]
长度为1和
2 : filter ((==1) . length . primeFactors) [3,5..]
评估为
2 : 3 : filter ((==1) . length . primeFactors) [5, 7..]
现在,您可能希望减少primeFactors 5
自己。
它在行动懒惰:)素数的名单开始非空,
primes = 2 : don't_know_yet_let's_see
和primeFactors
使用质数列表计算数量的主要因素。但要找出任何数字'n'的主要因素,我们只需要知道达到sqrt(n)
的质数。所以primes
尾巴,
filter ((== 1) . length . primeFactors) [3, 5 .. ]
可以使用什么已知的primes
。要检查3
,我们
factor 3 (2:don't_kow_yet_let's_see)
| 2*2 > 3 = [3]
| don't_care_above_was_true
如果我们开始与任何n
,说n = 35
尽量简短,
factor 35 (2:??)
| 2*2 > 35 -- False, next clause
| 35 `mod` 2 == 0 -- False, next clause
| otherwise = factor 35 ??
现在我们需要找出??
是。我们看到上面说的filter
ING让3遍,所以它的3:???
,因此
factor 35 (3:???)
| -- first two guards are False
| otherwise = factor 35 ???
现在什么???
?那么,filter ((== 1) . length . primeFactors) [5, 7 .. ]
,让我们看看是否5
通过过滤
factor 5 (2:3:???) -- note, we already know the first two elements of primes
| 2*2 > 5 -- False
| 5 `mod` 2 == 0 -- False
| otherwise = factor 5 (3:???)
| 3*3 > 5 = [5]
所以5
传球和我们知道的primes
前三个元素。在35因式分解,我们继续
factor 35 (5:????)
| 5*5 > 35 -- False
| 35 `mod` 5 == 0 = 5 : factor (35 `div` 5) (5:????)
factor 7 (5:????)
| 5*5 > 7 = [7]
所以,因子分解数字时,素数的名单需要尽可能,每个新总理将在它的要求来决定建立起来的,在那个时候,所有的已经找到确定下一个素数所需的素数。
真棒回答。帮了我一吨。我真的很感激你的时间,我想我终于能够应付懒惰了。 – greggreg 2012-02-08 00:11:50
你见过的斐波那契数的递归定义? '的FIB = 1:1:zipWith(+)的FIB(尾的FIB)'?你明白吗?这是一个以递归定义的数据开始的好地方。 – rampion 2012-02-07 18:58:01