2016-09-10 1 views
0

問題23は、「2つの豊富な数値の和ではない」すべての数値の合計を求めています。 1 + 2 + 3 + 4 + 6 = 16> 12であるため、n-12が最初の豊富な数である場合、整数nは豊富です。これにより、24 2つの豊富な数字の合計である最小の数字です。したがって、合計から除外したいと考えています。プロジェクトオイラー23 - 私の答えは大きすぎます

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個の+の過剰数が、ある場合(:

は、ここに私のpython私は、多くのバリエーションを試してみたコード、が、同じ考え方を使用しますij)= iは豊富な数字の合計ですので、数字のリストから削除します。残りのすべての数を合計します。これがどうして失敗するのか分かりません。しかし、結果は(別の情報源から得た)4179871でなければならないが、私は常に477倍以上の大きさの197711987の球場で何かを得る。

これが正しい結果を生成する方法を実際に理解できません。私が思っていることをしていない行があるはずですが、ここにあるものはすべてただ単純です私にはそれらの疑いがあります。私は多量の数値を計算する際に最も誤りがあると思っていましたが、私はほぼ完全にその部分が正しいと確信しています(28123未満の豊富な数値のリストを生成するコードを取得すれば、これは、WolframAlphaが28123以下の数の豊富な数字です)。

答えて

3

問題は、反復処理中にリストnumbersを変更しようとしていることです。これにより、期待している数よりも少ない数を削除できます。

あなたはそのコピー反復処理する必要があります。あなたも、数字の上にforループだけ繰り返し処理を見ることができるように

>>> numbers = list(range(10)) 
>>> for i in numbers: 
...  if i%2 == 0: 
...   numbers.remove(i) 
...  print(i) 
... 
0 
2 
4 
6 
8 

:これを考える何が起こっているかを理解するために

for i in list(numbers): 
    for j in range(1,i): 
     if is_abun(j) and is_abun(i-j): 
     numbers.remove(i) 
     break 

を。

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 = [1,2,3,4,..., 9]を持ってnumbersから0を削除:上記forループは、次のとほぼ同等だからです。値1が位置0で終わったことに注意してください。次の反復にはi = 1とがありますので、番号1をスキップしました。

数字を削除するたびにリストが変更されます。この変更によってアイテムが左にシフトすると、効果的にスキップされます。そのため、リストのコピーをにコピーしたいのです。この方法で元のリストを変更しても、反復処理中に "yielded"された数字には影響しません。

+0

編集しました。 (以前は約5秒かかっていました!)これが唯一の問題であるかどうかはすぐにわかります。私は多くのバリエーションを試したと言いました。 1つはnumbers.remove(i)の代わりにnumbers [i] = 0でした。これは、あなたが言及したシフトを引き起こすことはありませんでしたが、私はまだ多かれ少なかれ同じ出力を持っていました。その場合何が起こったのでしょうか? – FireGarden

+0

@FireGardenまあ、1つの簡単な方法は、不当な数を再計算することを避けることです。つまり、あなたのコードは 'is_abun(1)' *を何度も呼び出していて、 'is_abun(2)'にも同じことが言えます。これを高速化する簡単な方法は、豊富な数の集合を最初に計算することです: 'abundants = {i for i in range(1,28123)is_abun(i)}' 'とし、そのループの中で' is_abun(j) 'jは豊富に、(ij)は豊富に 'is_abun(ij)'とする。 – Bakuriu

+0

@FireGardenこの 'abundants'セットでいくつの数が終了するかによって、すべての可能な合計を計算し、この値を' n'までのガウス合計から削除する方が速いかもしれません。 – Bakuriu

関連する問題