Ruby 在我的代码中是否有一个无限循环用于求解Collatz序列?
我的代码试图找到这个问题的答案:为正整数集定义了以下迭代序列:Ruby 在我的代码中是否有一个无限循环用于求解Collatz序列?,ruby,Ruby,我的代码试图找到这个问题的答案:为正整数集定义了以下迭代序列: n → n/2 (n is even) n → 3n + 1 (n is odd) 使用上述规则并从13开始,我们生成以下序列: 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1 可以看出,从13开始到1结束的序列包含10个术语。虽然科拉兹问题尚未得到证实,但人们认为所有的起始数字都以1结束 哪一个起始数字,在一百万以下,产生的链条最长 注:一旦链开始,条款允许超过一百万 这是我的代码: st
n → n/2 (n is even)
n → 3n + 1 (n is odd)
使用上述规则并从13开始,我们生成以下序列:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
可以看出,从13开始到1结束的序列包含10个术语。虽然科拉兹问题尚未得到证实,但人们认为所有的起始数字都以1结束
哪一个起始数字,在一百万以下,产生的链条最长
注:一旦链开始,条款允许超过一百万
这是我的代码:
step_count = 1
score = {}
largest_score = 1
(1..1000000).map do |n|
while n >= 1 do
if n%2 == 0 then
n/2
step_count += 1
else
(3*n)+1
step_count += 1
end
end
score = {n => step_count}
end
score.each {|n, step_count| largest_score = step_count if largest_score < step_count}
puts score.key(largest_score)
我运行了一个多小时,仍然没有回答。在我的代码中是否存在无限循环,或者可能存在一些不同的问题,如果是,是什么问题
我使用的是Ruby 1.8.7,是的,你有一个无限循环。在这里:
while n >= 1 do
if n%2 == 0 then
n/2
step_count += 1
else
(3*n)+1
step_count += 1
end
end
while循环中的条件正在测试n,但循环中的任何内容都不会改变其值。您可能想做的是:
while n >= 1 do
if n % 2 == 0
n = n / 2
step_count += 1
else
n = (3 * n) + 1
step_count += 1
end
end
一些旁注:
看起来您的意思是用新的键值对更新分数散列,但正如所写的,分数={n=>step_count}将在每次迭代中完全替换它。要将新对添加到现有散列中,请使用score[n]=step\u count。
通过键查找散列中的值要比通过键查找散列中的值有效得多,因此您可能希望反转散列存储:score[step_count]=n,用score查找最大的分数。每个{step_count,n |…用score[maximust_score]读取它。这还有一个额外的优点,即您不必存储所有的一百万个结果;它只存储您到达的最后一个数字,从而生成给定长度的链。当然,这也意味着您只会看到一个数字生成最大的链,即使有多个数字具有相同的、最高的链长度!问题是答案似乎是独一无二的,但如果答案不是独一无二的,你就不会发现。
要在将来调试类似的问题,将循环迭代次数减少到10次是很方便的,比如说,在循环中散布一些puts语句,以观察正在发生的事情并感受执行流。
是的,你有一个无限循环。它在这里:
while n >= 1 do
if n%2 == 0 then
n/2
step_count += 1
else
(3*n)+1
step_count += 1
end
end
while循环中的条件正在测试n,但循环中的任何内容都不会改变其值。您可能想做的是:
while n >= 1 do
if n % 2 == 0
n = n / 2
step_count += 1
else
n = (3 * n) + 1
step_count += 1
end
end
一些旁注:
看起来您的意思是使用新的键值对更新分数散列,但如前所述,分数={n=>step_count}将在每次迭代中完全替换它。若要向现有散列添加新的对,请使用分数[n]=step_count。
通过键查找散列中的值要比通过键查找散列中的值有效得多,因此您可能希望反转散列存储:score[step_count]=n,用score查找最大的分数。每个{step_count,n |…用score[maximust_score]读取它。这还有一个额外的优点,即您不必存储所有的一百万个结果;它只存储您到达的最后一个数字,从而生成给定长度的链。当然,这也意味着您只会看到一个数字生成最大的链,即使有多个数字具有相同的、最高的链长度!问题是答案似乎是独一无二的,但如果答案不是独一无二的,你就不会发现。
要在将来调试类似的问题,将循环迭代次数减少到10次是很方便的,比如说,在循环中散布一些puts语句,以观察正在发生的事情并感受执行流。
请针对您的问题尝试以下解决方案:
def solve(n)
max_collatz = 0; max_steps = 0
(1..n).each do |k|
next if k % 2 == 0
next if k % 3 != 1
steps = collatz_sequence_count(k)
if steps > max_steps
max_steps = steps
max_collatz = k
end
end
max_collatz
# answer: 837799 with 525 steps, in nearly 2.2 seconds on my machine
end
def collatz_sequence_count(k)
counter = 1
while true
return counter if k == 1
k = k % 2 == 0 ? k/2 : 3 * k + 1
counter += 1
end
end
# You can then use the above methods to get your answer, like this:
answer = solve 1000000
puts "answer is: #{answer}"
Results使用定制的自制宝石解决以下问题:
nikhgupta at MacBookPro in ~/Code/git/ProjectEuler [ master: ✗ ] 48d
± time euler solve 14 +next: 2 | total: 22 | ▸▸▸▹▹▹▹▹▹▹
0014 | Longest Collatz sequence | It took me: 2.166033 seconds. | Solution: 837799
euler solve 14 3.30s user 0.13s system 99% cpu 3.454 total
请针对您的问题尝试以下解决方案:
def solve(n)
max_collatz = 0; max_steps = 0
(1..n).each do |k|
next if k % 2 == 0
next if k % 3 != 1
steps = collatz_sequence_count(k)
if steps > max_steps
max_steps = steps
max_collatz = k
end
end
max_collatz
# answer: 837799 with 525 steps, in nearly 2.2 seconds on my machine
end
def collatz_sequence_count(k)
counter = 1
while true
return counter if k == 1
k = k % 2 == 0 ? k/2 : 3 * k + 1
counter += 1
end
end
# You can then use the above methods to get your answer, like this:
answer = solve 1000000
puts "answer is: #{answer}"
Results使用定制的自制宝石解决以下问题:
nikhgupta at MacBookPro in ~/Code/git/ProjectEuler [ master: ✗ ] 48d
± time euler solve 14 +next: 2 | total: 22 | ▸▸▸▹▹▹▹▹▹▹
0014 | Longest Collatz sequence | It took me: 2.166033 seconds. | Solution: 837799
euler solve 14 3.30s user 0.13s system 99% cpu 3.454 total
非常感谢!你认为代码需要多长时间才能完成?这取决于很多事情,比如你正在使用什么样的硬件,以及你在那台机器上运行了多少其他东西!但是,如果它运行超过一分钟左右,我会怀疑。试着在循环中放入一些puts语句,以确保你正在取得进展,或者是narro在你不在的地方。非常感谢!你认为代码需要多长时间才能完成?这取决于很多事情,比如你正在使用什么样的硬件以及你在那台机器上运行了多少其他东西!但是,如果它运行超过一分钟左右,我会很怀疑。试着在你的循环中放入一些puts语句,以确保你成功我在我的macbook air上的TextMate中运行了它,在48.08秒后,它给了我一个空白screen@user3127905:我想不出原因。用我运行的结果更新了答案。它将答案放在哪里,例如,完成后哪个变量应该有答案?@user3127905:oh!t解1000000行返回解。因此,您可以使用puts来显示ans
威尔。我已经更新了我的代码来反映这一点。你能解释一下外循环中的优化吗?接下来的两个if语句?我在我的macbook air上的TextMate中运行了两个gigs的ram,48.08秒后它给了我一个空白screen@user3127905当前位置我想不出理由。用我运行的结果更新了答案。它将答案放在哪里,如,完成后哪个变量应该有答案?@user3127905:oh!solve 1000000行返回解决方案。因此,您可以使用puts来显示答案。我已经更新了我的代码来反映这一点。请您解释一下外循环中的优化以及接下来的两个if语句,好吗?您可能想了解有关此问题的更多信息。我在其他地方读到,已经表明,从1到n开始的序列中的最长序列并不比从n+1到2n开始的序列中的最长序列长,这意味着您只需查看从500001到1000000之间开始的序列。您可能需要查找有关此问题的更多信息。我在其他地方读到,已经证明,从1到n开始的序列中的最长序列并不比从n+1到2n开始的序列中的最长序列长,这表明你只需要看看从500001到1000000之间开始的序列。