了解Ruby逻辑运算符

时间:2011-06-14 08:43:06

标签: ruby logical-operators

我是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方式。

我在这里做错了什么?

2 个答案:

答案 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