我正在尝试根据Collatz序列填充数组。序列的约束如下:
正整数:
n→n / 2(n是偶数)
n→3n + 1(n为奇数)
示例输出
3 - > 10 - > 5 - > 16 - > 8 - > 4 - > 2 - > 1
理想情况下,我想构建一个递归调用,根据序列的约束填充数组。但是,我相信我的递归调用逻辑是非常有缺陷的。预期的行为是迭代嵌套数组,只操纵每个子数组的最后一个元素,直到元素达到1.我试图建立我对递归的理解,并希望有关如何解决这个问题的任何建议。
def collatzSum(maxNumber)
sequenceHash = Hash.new(0)
i = maxNumber
until i == 0 do
if i.even?
sequenceHash[i] = [(i), (i / 2)]
elsif i.odd? && i != 1
sequenceHash[i] = [(i), (3 * i + 1)]
elsif i == 1
sequenceHash[i] = [i]
end
i -= 1
end
p sequenceHash
helper_method递归。方法应该接受哈希值并根据if语句进行迭代。
=begin
desired output
hash = {5=>[5,16, 8, 4, 2,1],
4=>[4,2,1],
3=>[3,10,5,16,8,4,2,1],
2=>[2,1],
1=>[1]}
=end
代码:
collatzChain = lambda do |k|
j = 0
k = j[-1]
until k == 1 do
if k.even?
sequenceHash[k] << (k / 2)
elsif k.odd?
sequenceHash[k] << (3 * k + 1)
end
end
j += 1
end
collatzChain.call(sequenceHash.values)
sequenceHash
end
collatzSum(5)
答案 0 :(得分:2)
所以你提到你想要一个递归算法,你当前的方法看起来是迭代的。要递归,您需要调用您所处的方法,使得值越来越接近基本条件,然后,一旦达到基本条件,就会返回,在调用链上构建返回值。因此,对于Collatz序列,递归方法看起来像:
def build_collatz_chain(max_number)
return_value = [max_number]
# our base condition is when the number passed in is equal to 1, so
# when we get 1 as the max_number, we'll return an array looking like
# [1]
return return_value if max_number == 1
if max_number.even?
# here, with an even max_number, we'll recurse and call our method
# again, passing in the new max_number, which is the current
# max_number / 2.
return_value + build_collatz_chain(max_number / 2)
else
# same as above, but we're odd, so we'll recurse with 3 * max_number + 1
return_value + build_collatz_chain(3 * max_number + 1)
end
end
现在当我们使用值5
来调用它时,最终会发生的事情是这样的:
call build_collatz_chain(5)
call build_collatz_chain(16)
call build_collatz_chain(8)
call build_collatz_chain(4)
call build_collatz_chain(2)
call build_collatz_chain(1)
We have hit the base condition! return with [1]
return from 2 with [2, 1]
return from 4 with [4, 2, 1]
return from 8 with [8, 4, 2, 1]
return from 16 with [16, 8, 4, 2, 1]
return from 5 with [5, 16, 8, 4, 2, 1]
所以,现在如果你想要一个散列的所有数字,直到传递给max_number
并将其Collatz链作为值,你可以使用帮助器为每个值调用它,最多为max(这个帮助器是迭代的,但可以进行递归...如果你想让它递归,请为观众锻炼):
def collatz_sum(max_number)
{ }.tap do |sequence_hash|
max_number.downto(1) do |i|
sequence_hash[i] = build_collatz_chain(i)
end
end
end
然后当你致电collatz_sum(5)
时,你会回来:
{5=>[5, 16, 8, 4, 2, 1], 4=>[4, 2, 1], 3=>[3, 10, 5, 16, 8, 4, 2, 1], 2=>[2, 1], 1=>[1]}
您的方法迭代的原因是在collatzChain
lambda中,您设置了一个值(j
),然后递增它并循环直到k
等于{{ 1}}。它也是一个无限循环,因为您最初将1
设置为:
k
所以j = 0
k = j[-1]
,然后你迭代到k == 0
,然后再也不会更新k == 1
的值。
答案 1 :(得分:1)
目前还不清楚这里是否需要递归操作,因为这似乎是值 x 和 f(x)之间的直接映射。通过切换到简单的数组输出,您可以实现您想要的目标:
SELECT
c.`competition_name`,
MAX(r.`result`),
s.`sportsman_name`
FROM `competition` c
INNER JOIN `results` r ON c.`competition_id` = r.`competition_id`
INNER JOIN `sportsman` s ON s.`sportsman_id` = r.`sportsman_id`
GROUP BY c.`competition_name`;