[英]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.