我正在处理Euler项目档案中的Longest Collatz问题,并且无法弄清楚为什么我的这个问题需要很长时间。我将它与其他成功的脚本进行了比较,这些脚本通常需要几秒钟。
下面是代码,但是想法是对于给定范围内的每个数字,程序开始强制下降。如果在下降的任何一点它找到了一个已经看到的数字并计算出它的下降,它只是将当前下降的长度加到先前确定的数字上。
我见过的其他代码也是如此,我无法弄清楚为什么我的并没有给它额外的速度。我运行它的范围高达1,000并且它工作正常并且吐出所有正确的答案,但是大约10,000,它减慢了速度,我的目标是1,000,000
为了记录,我非常新编程(已经在Python工作了一个星期),但对数论非常熟悉。
编辑:稍微调整一下代码,感谢Glibdud!
collatz_dic = {1:3}
d=1
for x in range(1,10001):
collatz_list = [x]
while x != 1:
if x % 2 == 0:
x = x/2
collatz_list.append(x)
if x in collatz_dic.keys() == True:
collatz_dic[d] = ((len(collatz_list)-1) + collatz_dic.get(x))
else:
collatz_dic[d] = (len(collatz_list)-1)
else:
x = (3*x)+1
collatz_list.append(x)
if x in collatz_dic.keys() == True:
collatz_dic[d] = ((len(collatz_list)-1) + collatz_dic.get(x))
else:
collatz_dic[d] = (len(collatz_list)-1)
d = d+1
print(max(collatz_dic, key=collatz_dic.get))
答案 0 :(得分:0)
这段代码中更重要的逻辑缺陷就是这句话:
if x in collatz_dic.keys() == True:
collatz_dic[d] = ((len(collatz_list)-1) + collatz_dic.get(x))
else:
collatz_dic[d] = (len(collatz_list)-1)
(两种情况都可以合并为一种。)在第一次break
任务之后应该有一个collatz_dic[d]
,因为你现在知道了答案,所以停止你的循环! else
子句不属于此处,而应该是else
循环的while
子句,因为我们现在还不知道答案,所以为什么继续将当前值保存到字典中。
次要编码问题包括:if
的两半中的大部分可以折叠成公共代码; collatz_list
不需要是一个列表,只需一个计数器;你不想这样做:
if x in collatz_dic.keys() == True:
而是:
if x in collatz_dic:
因为您不需要构建一个新的数据结构来进行搜索,当您拥有一个特别快的时候。将所有这些修复与一些样式更改放在一起,我们得到:
collatz_dic = {1: 3}
for d in range(2, 1_000_001):
x = d
collatz_count = 0
while x != 1:
if x % 2 == 0:
x = x / 2
else:
x = 3 * x + 1
collatz_count += 1
if x in collatz_dic:
collatz_count += collatz_dic[x]
break
collatz_dic[d] = collatz_count
print(max(collatz_dic, key=collatz_dic.get))
在5秒内解决1,000,000(837,799),完全在1分钟的时限内。