我一直在努力学习递归。这是找到前n个数字之和的解决方案。但是,如果我们希望第一个数字为0怎么办?如果第一个数字从0开始,有人可以帮我写一个对前n个数字求和的递归算法吗?
因此,代替first_even_numbers_sum(5)是[2,4,6,8,10]的总和。 其[0,2,4,6,8]并递归求解。
def first_even_numbers_sum(n)
return 2 if n == 1
n*2 + first_even_numbers_sum(n-1)
end
first_even_numbers_sum(4)
答案 0 :(得分:1)
我建议以下。
def add_em_up(n)
return 1 if n == 2
n - 1 + add_em_up(n - 1)
end
在编写递归时,添加一些puts
语句以查看发生了什么,即使对经验丰富的红宝石也很有帮助。让我们开始吧。
def add_em_up(n)
puts "entered add_em_up(#{ n })"
puts "returning 1 when n = #{ 2 }" if n == 2
return 1 if n == 2
puts "calling add_em_up(#{ n - 1 }) when n = #{ n }"
t = n - 1 + add_em_up(n - 1)
puts "returning #{ n } - 1 + #{t - n + 1} = #{t} when n = #{ n }"
t
end
add_em_up(5)
#=> 10
entered add_em_up(5)
calling add_em_up(4) when n = 5
entered add_em_up(4)
calling add_em_up(3) when n = 4
entered add_em_up(3)
calling add_em_up(2) when n = 3
entered add_em_up(2)
returning 1 when n = 2
returning 3 - 1 + 1 = 3 when n = 3
returning 4 - 1 + 3 = 6 when n = 4
returning 5 - 1 + 6 = 10 when n = 5
您可以使用缩进使情况更清晰。
INDENT = 3
$col = 0
def add_em_up(n)
s = " " * $col
puts "#{ s }entered add_em_up(#{ n })"
puts "#{ s }returning 1 when n = #{ 2 }" if n == 2
$col -= INDENT if n == 2
return 1 if n == 2
puts "#{ s }calling add_em_up(#{ n - 1 }) when n = #{ n }"
$col += INDENT
t = n - 1 + add_em_up(n - 1)
puts "#{ s }returning #{ n } - 1 + #{t - n + 1} = #{t} when n = #{ n }"
$col -= INDENT
t
end
add_em_up(5)
#=> 10
entered add_em_up(5)
calling add_em_up(4) when n = 5
entered add_em_up(4)
calling add_em_up(3) when n = 4
entered add_em_up(3)
calling add_em_up(2) when n = 3
entered add_em_up(2)
returning 1 when n = 2
returning 3 - 1 + 1 = 3 when n = 3
returning 4 - 1 + 3 = 6 when n = 4
returning 5 - 1 + 6 = 10 when n = 5
请注意,在此方法的第一个版本(无缩进)中,可以替换
t = n - 1 + add_em_up(n - 1)
puts "returning #{ n } - 1 + #{t - n + 1} = #{t} when n = #{ n }"
t
使用
(n - 1 + add_em_up(n - 1)).
tap { |t| puts "returning #{ n } - 1 + #{t - n + 1} = #{t} when n = #{ n }" }
或(如评论中指出)
(n - 1 + add_em_up(n - 1)).yield_self { |t|
puts "returning #{ n } - 1 + #{t - n + 1} = #{t} when n = #{ n }"; t }
在这里,更一般地说,方法Object#tap对于调试非常有用。 Object#yield_self(Ruby v2.5中的新功能)是另一种有用的方法。