检查范围内的任何数模数是否为零

时间:2014-03-29 10:47:31

标签: ruby algorithm

有一个函数d(n)被定义为n的适当除数之和(小于n的数字均匀分成n)。例如,220的适当除数是1,2,4,5,10,11,20,22,44,55和110;因此d(220)= 284. 284的适当除数是1,2,4,71和142;所以d(284)= 220。

我想在Ruby中实现这个d(n)函数。我的第一直觉是使用for循环遍历所有值到n并检查模数。以下代码有效:

我可以使用这样的for循环来实现它:

def d(n)
  proper_divisors = []
  for i in 1...n
    if (n % i == 0)
      proper_divisors.push(i)
    end
  end
  return proper_divisors.inject(:+)
end

但是从之前的回答中我了解到it's very rare to use a for loop in Ruby。这就是我尝试这个的原因:

def d(n)
  (1..n).inject(0) { |total| total+ n if (n % (1..n) == 0) }
end 

因此,根据1 to n的值,我从total开始等于0并将n添加到total,如果n可以平均分为数字从1到n。自if (n % (1..n) == 0)以来,Range can't be coerced into Fixnum (TypeError)部分无效。

如何实现我对一个范围取一个数的模数,如果它等于零则返回true?

3 个答案:

答案 0 :(得分:4)

(toro2k的答案的固定版本)

def d(n)
  (1..n/2).inject(0) { |total, m| (n % m).zero? ? total + m : total }
end

d(220) # => 284

阻止inject接受两个参数:集合的累加器和当前元素。该块应该返回累加器的新值。在您的代码中,您忽略当前元素(这会让您尝试将n除以范围)

答案 1 :(得分:2)

我做了以下事情: -

def d(n)
  (1..(n/2)).each_with_object(total = 0){|ele| total += ele if n%ele == 0 }
  total
end 

答案 2 :(得分:2)

效率不如Sergio Tulentsev的答案,但更简单:

def d n
  (1..n / 2).select{|m| (n % m).zero?}.inject(:+)
end