これらの関数は両方とも、本質的に同じ方法で同じもの (関連付けられたコラッツ シーケンスの長さが n 以下になるような整数の数) を計算します。唯一の違いは、前者はセットのみを使用するのに対し、後者はセットとリストの両方を使用することです。
2 つ目は (少なくとも Python 3.2 の IDLE で) メモリ リークを起こしますが、1 つ目はそうではありません。その理由はわかりません。私はいくつかの「トリック」(del
ステートメントの追加など)を試しましたが、何も役に立たないようです(驚くことではありません。これらのトリックは役に立たないはずです)。
何が起こっているのかを理解するのを手伝ってくれる人に感謝します。
コードをテストする場合は、おそらくn
55 ~ 65 の範囲の値を使用する必要があります。75 を超えると、ほぼ確実に (完全に予想される) メモリ エラーが発生します。
def disk(n):
"""Uses sets for explored, current and to_explore. Does not leak."""
explored = set()
current = {1}
for i in range(n):
to_explore = set()
for x in current:
if not (x-1) % 3 and ((x-1)//3) % 2 and not ((x-1)//3) in explored:
to_explore.add((x-1)//3)
if not 2*x in explored:
to_explore.add(2*x)
explored.update(current)
current = to_explore
return len(explored)
def disk_2(n):
"""Does exactly the same thing, but Uses a set for explored and lists for
current and to_explore.
Leaks (like a sieve :))
"""
explored = set()
current = [1]
for i in range(n):
to_explore = []
for x in current:
if not (x-1) % 3 and ((x-1)//3) % 2 and not ((x-1)//3) in explored:
to_explore.append((x-1)//3)
if not 2*x in explored:
to_explore.append(2*x)
explored.update(current)
current = to_explore
return len(explored)
EDIT : これは、インタプリタのインタラクティブ モード (IDLE なし) を使用する場合にも発生しますが、ターミナルからスクリプトを直接実行する場合には発生しません (その場合、メモリ使用量は、関数が返された後、またはすぐに通常に戻ります)。への明示的な呼び出しがあるためgc.collect()
)。