问题描述
|
我是Ruby的新手,并认为这是通过解决Euler项目中的问题而学习更多的好方法。
这是我对问题5使用蛮力想到的:
#What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
end_point = 1_000_000_000
start_point = 2_520
(start_point..end_point).each do |number|
flag = true
(2..20).each do |divisor|
flag = flag & ( number % divisor ) == 0 ? true : false
end
print number.to_s + \"\\n\" if flag
end
这运行了很长时间,没有给出任何答案。
然后,我使用相同的逻辑编写C ++程序来完成相同的任务:
#include<iostream>
using namespace std;
int main()
{
unsigned long int solution = 2520;
while(1)
{
bool flag = true;
for(int divisor=2;divisor<=20;divisor++)
{
if( solution % divisor == 0)
flag = flag & true;
else{
flag = false;
break;
}
}
if(flag == true){
cout<<solution<<endl;
break;
}
solution++;
}
return 0;
}
这为我提供了正确的解决方案,并且运行了将近一秒钟。由于Ruby是经过解释和C ++编译的,所以执行时间并不是我真正关心的问题,但是Ruby返回正确答案的失败确实让我感到惊讶。我认为这可能是因为我尝试编写C ++ Ruby样式而不是实际的Ruby方法。
我在这里做错了什么?
解决方法
注意:我尚未运行以下任何一种建议的解决方案来完成它们-它们仍然需要很长时间-因此不能保证正确性!
问题是您更新
flag
的行。您使用的是&
(按位与)而不是&&
(布尔与)。
在其他问题中,&
的运算符优先级高于==
,因此您的行被解释为(因为? true : false
是多余的):
flag = (flag & (number % divisor)) == 0
现在,似乎true & some_integer
是true
,而不是== 0
,因此flag
始终设置为false
。
相反,您想要:
flag = flag && (number % divisor == 0)
或者,更简洁和Rubyish:
flag &&= number % divisor == 0
一种替代解决方案是:
i = 1
while true
break unless (2..20).any? {|d| i % d != 0}
i+=1
end
puts i
, 实际上,我无需编写程序即可解决此问题。
这是我使用的逻辑:
写下所有小于20(目标)的质数。
[2,3,5,7,11,13,17,19]
对于每个质数,将其提高到小于目标(20)的最大功率。
2**4 * 3**2 * 5 * 7 * 11 * 13 * 17 * 19
要以编程方式执行此操作,请使用Eratosthenes筛-http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes算法对素数进行迭代。对于列表中的每个质数,找到将其提高到小于目标数(20)的最大幂。您可以使用以下公式找到幂:(Math.log(target)/Math.log(i)).floor
假设您得到素数数组:nums = [2,19]
然后,您可以使用以下方法轻松获得答案:
nums.map {|i| i**((Math.log(target)/Math.log(i)).floor)}.inject(:*)