递归地找到3和5的乘积的所有自然数

  • 本文关键字:自然数 递归 ruby
  • 更新时间 :
  • 英文 :


如果我们列出所有10以下的自然数,它们是3或5的倍数,我们得到3、5、6和9。这些倍数之和是23。求出1000以下所有3或5的倍数之和。

def multiples_of(number)
number = number.to_f - 1.0
result = 0
if (number / 5.0) == 1 || (number / 3.0) == 1
return result = result + 5.0 + 3.0
elsif (number % 3).zero? || (number % 5).zero?
result += number 
multiples_of(number-1)
else 
multiples_of(number-1)
end
return result
end
p multiples_of(10.0)

我的代码返回的是9.0,而不是23.0。

使用核心方法选择&范围求和

目前还不完全清楚你到底想在这里做什么。这显然是一项家庭作业,所以它可能是为了让你以某种方式思考课程。如果是这样,请参考你的课程计划或询问你的老师。

也就是说,如果你将可能的输入值集限制为整数,并使用迭代而不是递归,那么你可以在一个互斥范围上使用Array#select,然后在中间结果上调用Array#sum来简单地解决这个问题。例如:

(1...10).select { |i| i.modulo(3).zero? || i.modulo(5).zero? }.sum
#=> 23
(1...1_000).select { |i| i.modulo(3).zero? || i.modulo(5).zero? }.sum
#=> 233168

如果要查看所有选定的值,请去掉"#和"。此外,您可以通过将逻辑与预期结果进行比较来创建自己的自定义验证器。例如:

def valid_result? range_end, checksum
(1 ... range_end).select do |i|
i.modulo(3).zero? || i.modulo(5).zero?
end.sum.eql? checksum
end
valid_result? 10, 9
#=> false
valid_result? 10, 23
#=> true
valid_result? 1_000, 233_168
#=> true

您的代码存在许多问题。最重要的是,您正在进行递归调用,但不会以任何方式组合它们的结果。

让我们逐步了解输入10会发生什么。

您指定的number = number.to_f - 1.0等于9。

然后你达到了elsif (number % 3).zero? || (number % 5).zero?条件,这是真的,所以你调用result += numbermultiples_of(number-1)

但是,不管怎样,您都会丢弃递归调用的返回值并调用return result。因此,您的递归对返回值没有任何影响。对于除3或5之外的任何输入,您将始终返回input-1作为返回值。这就是为什么你得了9分。

以下是一个可以进行比较的实现:

def multiples_of(number)
number -= 1
return 0 if number.zero?
if number % 5 == 0 || number % 3 == 0
number + multiples_of(number)
else
multiples_of(number)
end
end
puts multiples_of(10)
# => 23

请注意,我调用multiples_of(number)而不是multiples_of(number - 1),因为您已经在递减函数第一行的输入。你不需要递减两次-这将导致你只处理每隔一个数字,例如9,7,5,3

解释

通过一点递归来帮助你理解它。假设我们有一个4的输入。

我们首先递减输入,使数字=3。然后我们达到if number % 5 == 0 || number % 3 == 0条件,所以我们返回number + multiples_of(number)

multiples_of(number)返回什么?现在我们必须评估下一个递归调用。我们把这个数字递减,所以现在我们得到了数字=2。我们遇到了else块,所以现在我们将返回multiples_of(number)

我们对数字为1的下一个递归调用执行相同的操作。这个multiples_of(1)。我们递减输入,所以现在我们的数字为0。这与我们的基本情况相匹配,所以最后我们完成了递归调用,并且可以向上计算堆栈,以计算出我们的实际返回值

对于6的输入,它看起来是这样的:

multiples_of(6)

5 + multiples_of(5)

multiples_of(4)

3 + multiples_of(3)

multiples_of(2)

multiples_of(1)

multiples_of(0)

0

可以从闭式表达式中获得所需的结果。也就是说,不需要迭代。

假设我们被给定一个正整数n,并且希望计算作为不超过n3的倍数的所有正数的和。

1*3 + 2*3 +...+ m*3 = 3*(1 + 2 +...+ m)

其中

m = n/3

1 + 2 +...+ m是算法表达式的和,由给出

m*(1+m)/2

因此,我们可以写:

def tot(x,n)
m = n/x
x*m*(1+m)/2
end

例如,

tot(3,9)  #=> 18 (1*3 + 2*3 + 3*3)
tot(3,11) #=> 18 
tot(3,12) #=> 30 (18 + 4*3)
tot(3,17) #=> 45 (30 + 5*3)
tot(5,9)  #=> 5  (1*5)
tot(5,10) #=> 15 (5 + 2*5)
tot(5,14) #=> 15 
tot(5,15) #=> 30 (15 + 3*5)

因此,不大于n的数之和是35的倍数,由下式给出:

def sum_of_multiples(n)
tot(3,n) + tot(5,n) - tot(15,n)
end

需要CCD_ 23,因为前两项加倍计数为CCD_。

sum_of_multiples(9)         #=> 23 (3 + 6 + 9 + 5)
sum_of_multiples(10)        #=> 33 (23 + 2*5)
sum_of_multiples(11)        #=> 33
sum_of_multiples(12)        #=> 45 (33 + 4*3) 
sum_of_multiples(14)        #=> 45 
sum_of_multiples(15)        #=> 60 (45 + 3*5)
sum_of_multiples(29)        #=> 195 
sum_of_multiples(30)        #=> 225 
sum_of_multiples(1_000)     #=> 234168 
sum_of_multiples(10_000)    #=> 23341668 
sum_of_multiples(100_000)   #=> 2333416668 
sum_of_multiples(1_000_000) #=> 233334166668 

最新更新