繁体   English   中英

欧拉计划23-无论我做什么,我的回答都太大了

[英]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 = 1numbers[1] == [1,2,3,4,...,9][1] == 2跳过了数字1

每次删除数字时,列表都会被修改,如果此修改导致项目向左移动,则实际上是在跳过它们。 这就是为什么要遍历列表副本的原因:这样,对原始列表的修改不会影响迭代过程中“屈服”的数字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM