我是Ruby的新手,并认为通过解决Project 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方式。
我在这里做错了什么?
答案 0 :(得分:3)
我实际上没有为它编写程序就解决了这个问题。 这是我使用的逻辑:
记下小于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, 3, 5, 7, 11, 13, 17, 19]
然后你可以通过以下方式轻松得到答案:
nums.map {|i| i**((Math.log(target)/Math.log(i)).floor)}.inject(:*)
答案 1 :(得分:2)
注意:我没有完成以下任何一种建议的解决方案 - 它们仍需要很长时间 - 所以无法保证正确性!
更新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