[英]Project Euler 23 - No matter what I do, my answer is far too big
问题23要求所有数字的总和,而不是两个丰富数字的总和。 我们只需要检查小于28123的数字。如果整数n的适当除数之和大于n,则整数n是充裕的-12是自1 + 2 + 3 + 4 + 6 = 16> 12以来的第一个整数。最小的数字,它是2个大量数字的总和,因此我们要从总和中排除它。
这是我的python代码,我尝试了很多变体,但是使用的是相同的想法:
import math
def divisors_of(n):
divs=[1]
for i in range(2,int(math.sqrt(n))+1):
if i**2 == n:
divs.append(i)
elif n%i == 0:
divs.append(i)
divs.append(n//i)
return divs
def is_abun(n):
return sum(divisors_of(n))>n
numbers=[i for i in range(1,28123)]
for i in numbers:
for j in range(1,i):
if is_abun(j) and is_abun(i-j):
numbers.remove(i)
break
print(sum(numbers))
想法很简单,如果j和ij是大量数字,那么j +(ij)= i当然是大量数字的总和,因此我将其从数字列表中删除。 然后,我总结所有剩余的数字。 我不知道这怎么可能失败。 但是,结果应该是(从其他来源获得)4179871,而我总是在197711987的范围内得到一些东西,它太大了47倍。
我真的不明白这怎么不能产生正确的结果。 必须有一些行不符合我的想法,但是这里的一切对我来说太简单了,无法怀疑它们。 我以为最可能的错误是在计算大量数字时,但是我几乎完全确定该部分是正确的(如果我按原样获取代码以生成少于28123的大量数字列表,则会得到长度为6965的列表,少于28123 WolframAlpha声称的数量)。
问题是您要在迭代列表numbers
时对其进行修改。 这导致您删除的数字少于预期的数字。
您应该遍历它的一个副本:
for i in list(numbers):
for j in range(1,i):
if is_abun(j) and is_abun(i-j):
numbers.remove(i)
break
要了解发生了什么,请考虑以下事项:
>>> numbers = list(range(10))
>>> for i in numbers:
... if i%2 == 0:
... numbers.remove(i)
... print(i)
...
0
2
4
6
8
如您所见, for
循环仅对偶数进行迭代。 这是因为上面的for
循环大致等同于以下内容:
i = 0
while i < len(numbers):
number = numbers[i]
if number % 2 == 0:
numbers.remove(number)
print(number)
i += 1
因此,当您第一次拥有i = 0
并因此使number = 0
,便从numbers
删除了0
,所以现在您有了numbers = [1,2,3,4,..., 9]
。 请注意,值1
如何在位置0
结束的,所以在下一次迭代中,我们有i = 1
和numbers[1] == [1,2,3,4,...,9][1] == 2
跳过了数字1
!
每次删除数字时,列表都会被修改,如果此修改导致项目向左移动,则实际上是在跳过它们。 这就是为什么要遍历列表副本的原因:这样,对原始列表的修改不会影响迭代过程中“屈服”的数字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.