2014-03-29 38 views
0

有一个函数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,并添加ntotal如果n可同样由数量从1分至n。自Range can't be coerced into Fixnum (TypeError)以来,if (n % (1..n) == 0)部分不起作用。

我该如何做到这一点,我将一个数字的模数对一个范围取反,如果它等于零,则返回true?

回答

4

(固定toro2k的回答的版本)

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

d(220) # => 284 

块到inject接受参数:蓄能器和所述收集的当前元素。该块应该返回累加器的新值。在你的代码忽略当前元素(它让你尝试将n由范围)

+0

只是使用n/2 .... –

+1

你可以优化循环到'(1..n/2)',看看'n/2'之后没有什么可以作为n的正确除数'? heh @AlokAnand,同样的想法^ _^ –

+0

是啊,谢谢你们:) –

2

我也做了以下内容: -

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

不到预期的效果塞尔吉奥Tulentsev的答案,但更简单:

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

谢谢。为什么效率不高? –

+0

因为它迭代了两次。 – sawa

+1

实际上,对于'n'高达10^9,你和塞尔吉奥图利塞夫的解决方案的表现几乎相同。 – toro2k

相关问题