我正在尝试创建一个脚本来为Project Euler解决一个问题,但它会不断返回MemoryError。我完全不知道为什么。
divisible = True
possible = dict()
for i in xrange(1, 100000000):
for n in xrange(1, 21):
if i%n != 0:
divisible = False
else:
if i in possible:
possible[i].append(n)
else:
possible[i] = [n]
if len(possible[i]) == 20:
print i
break
Python似乎认为它出现在这一行possible[i] = [n]
答案 0 :(得分:2)
问题出在您的行中
if len(possible[i]) == 20:
你的意思是说
if len(possible) == 20:
实际上,你的代码会继续运行 - 大概是因为循环计数太大了,一些堆栈会填满......
另外 - 虽然我不确定你想要实现什么,但是你的break
命令位于最里面的循环中 - 所以你突破它,然后再次出现...并且因为长度只有20
一次,你仍然卡住了。检查你的逻辑。
例如,对代码进行以下小改动会产生有用的输出(虽然我不知道它对你有用......但它可能会给你一些想法):
divisible = True
possible = dict()
for i in xrange(1, 100000000):
for n in xrange(1, 21):
if i%n != 0:
divisible = False
else:
if i in possible:
possible[i].append(n)
else:
possible[i] = [n]
if len(possible) == 20:
print i
break
else:
print i, possible[i]
输出:
1 [1]
2 [1, 2]
3 [1, 3]
4 [1, 2, 4]
5 [1, 5]
6 [1, 2, 3, 6]
7 [1, 7]
8 [1, 2, 4, 8]
9 [1, 3, 9]
10 [1, 2, 5, 10]
11 [1, 11]
12 [1, 2, 3, 4, 6, 12]
13 [1, 13]
14 [1, 2, 7, 14]
15 [1, 3, 5, 15]
16 [1, 2, 4, 8, 16]
17 [1, 17]
18 [1, 2, 3, 6, 9, 18]
19 [1, 19]
20
编辑更仔细地阅读代码,我认为你要做的是找到具有正好20个因素的数字;因此你的情况是正确的。问题是你也存储了所有其他条款 - 这是一个非常大量的列表。如果你只是在最后一个数字之后(在休息之前所有输出都是i
之后),那么你真的不需要保留所有其他条款。以下代码就是这样 - 它在我的计算机上运行得很快,现在耗时大约20 MB的内存(但还没有答案......)
divisible = True
possible = [];
biggest = 0;
bigN = 100000000;
for i in xrange(1, bigN):
for n in xrange(1, 21):
if i%n != 0:
divisible = False
else:
if len(possible) > 0:
possible.append(n)
else:
possible = [n]
if len(possible) >= 20:
print i
print possible
break
else:
if bigN < 1000:
print i, possible; # handy for debugging
if biggest < len(possible):
biggest = len(possible);
possible = []
计算你正在做的事情的“手动”方式是找到所有数字从1到20的主要因子;计算每个素数出现的最大次数;并采取他们的产品:
2 = 2
3 = 3
4 = 22
5 = 5
6 = 2 3
7 = 7
8 = 222
9 = 33
10 = 2 5
11 = 11
12 = 22 3
13 = 13
14 = 2 7
15 = 3 5
16 = 2222
17 = 17
18 = 2 33
19 = 19
20 = 22 5
答案:(2 * 2 * 2 * 2)*(3 * 3)* 5 * 7 * 11 * 13 * 17 * 19 = 232792560
答案 1 :(得分:0)
由于大小:
导致内存错误possible = dict()
你继续将整数推入其中,它的大小不断增长,你会得到内存错误。 仔细查看是否可以在解决方案中避免这种情况。如果答案仅需要告知因子的数量,而不是所有因素,则不要将所有值存储在列表中并计算其长度。 而是为每个数字增加计数器。 我不确定问题是什么,但可以用以下内容代替:
if len(possible[i]) == 20:
print i
break
可以是:
if i in possible:
possible[i] += 1
else:
possible[i] = 0
if possible[i] == 20:
print i
break
答案 2 :(得分:0)
快速回退信封计算。你有类似100000000
整数的东西,如果你存储它们全部都是大约0.4 Gb(在C中)。当然,这些是python整数,所以每个都超过4个字节......在我的系统中,每个都是24(!)字节,这需要0.4 Gb到2.34 Gb。现在你将每个存储在最多21个列表中...这样(最多)每个指向另外21个指针。假设指向int的4byte指针,您可以看到我们已经开始消耗大量内存。
另请注意,出于性能原因,列表被过度分配。可能你使用的内存比你需要的多,因为你的列表还没有填满。
当然,你实际上并没有将它们全部存放起来,并且你有一个早期休息状态(显然)没有被击中。你可能在某处出现了逻辑错误。
答案 3 :(得分:0)
检查应该在内环之外,以便正确终止。否则,程序将永远不会在预定的退出处停止。
divisible = True
possible = dict()
for i in xrange(1, 100000000):
for n in xrange(1, 21):
if i%n != 0:
divisible = False
else:
if i in possible:
possible[i].append(n)
else:
possible[i] = [n]
if len(possible[i]) == 20:
print i
break
BTW,更快的方法是找到LCM而不是像这样的强力方法。
编辑: 一种不使用记忆的变体。
divisible = True
possible = []
for i in xrange(0, 1000000000):
count = 0
for n in xrange(1, 21):
if i%n != 0:
divisible = False
else:
count += 1
if count == 20:
possible.append(i)
print i
else:
print "\r", "%09d %d %d" % (i, 232792560, count),
print possible
答案 4 :(得分:0)
我想说你需要在这里改变方法。您需要符合1分钟规则的解决方案。并且在这里讨论解决方案违背了Project Euler的目的。所以我建议您考虑一种不同的方法来解决问题。一种可能在不到一秒钟内解决问题的方法。
至于内存问题,使用当前的方法,几乎不可能摆脱它。因此,改变方法也将解决这个问题。虽然这篇文章没有回答你的问题,但这符合Project Euler的原则!