Trying to find largest prime factor
这来自于关于项目欧拉的第三个问题:
https://projecteuler.net/问题=3
问题:13195的主要因素是5、7、13和29。数字600851475143的最大主因子是什么?
因为这是一个谜,我不喜欢使用罐装的Ruby方法。所以这就是…
当前逻辑:num是我们要查找的质数因子。候选人是一个潜在的主要因素sqrt是num的平方根
1 | until candidate >= sqrt |
我从埃拉托森的筛网中借用了这个想法来寻找素数,在这里算法检查到num平方根的每个数的可除性。候选者是测试num是否有除数的数字。
1 2 3 | if num % candidate == 0 ... end |
号
目的是检查num是否可以被任何东西整除(具有因子)。如果num不能被候选者整除,那么候选者将增加1,直到
如果num可以被候选者整除,那么我们就知道候选者是质数,它被插入质数因子中。然后递归会测试新定义的num。
1 | prime_factors << num |
如果
问题:
问题不在于它超时了,而在于它给出了错误的答案。我的代码循环似乎超出了需要。我添加了一些日志。我不知道为什么,但我认为这和递归部分有关。诚然,我从不在代码中使用递归,我想用它来扩展我的技能集。所以递归在概念上对我来说是模糊的。任何阅读也会有帮助。
应该发生什么:主因子=[2,2,19]Prime_Factors.Last=19
实际发生的情况:主因子=[2,2,19,19,38]Prime_Factors.Last=38
整个代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def largest_prime_factor(num,prime_factors) puts"beg fx: num: #{num}, prime_factors: #{prime_factors} candidate = 2 sqrt = Math.sqrt(num) loop_count = 0 until candidate >= sqrt if num % candidate == 0 num = num / candidate prime_factors << candidate largest_prime_factor(num,prime_factors) end candidate += 1 loop_count +=1 end puts"outside loop: candidate >= sqrt is #{candidate >= sqrt} num: #{num}, prime_factors: #{prime_factors}, candidate: #{candidate}, sqrt: #{sqrt}, loop: #{loop_count}" gets prime_factors << num prime_factors.last end |
。
因此,正如您所建议的,问题似乎是递归逻辑。
仅仅因为你递归地调用一个函数并不意味着"父"停止工作——他只是坐着等待"子"完成,然后继续工作。这就是这种"循环过度"发生的地方。代码实际上不是循环过度,而是结束。
您可以在Puts语句中看到这一点。注意,在循环停止后,sqrt会增加,因为脚本现在正在运行父代码,而不是在递归块(子)完成之后。
为了解决这个问题,我做了两件事:1。创建一个布尔值,指示代码块已经历递归。如果是,运行此代码,否则…做点别的。2。如果候选者不是2,则递增2。这将跳过测试除2之外的所有偶数。没有必要测试其他偶数,因为它不是素数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def largest_prime_factor(num,prime_factors,recursive) candidate = 2 until candidate >= Math.sqrt(num) recursive = false if num % candidate == 0 num = num / candidate recursive = true prime_factors << candidate largest_prime_factor(num,prime_factors,recursive) end break if recursive candidate == 2 ? candidate += 1 : candidate += 2 end prime_factors << num unless recursive prime_factors.last end |