最近、重要な制約を持つ特定のシーケンスを生成する関数を作成しました。問題は自然な再帰的解決策にありました。さて、入力が比較的小さい場合でも、シーケンスは数千であるため、すべてのシーケンスでリストを埋めるために使用するのではなく、ジェネレーターとしてアルゴリズムを使用することをお勧めします。
これが例です。再帰関数を使用して文字列のすべての順列を計算するとします。次の素朴なアルゴリズムは、追加の引数'storage'を取り、それが見つかるたびに順列を追加します。
def getPermutations(string, storage, prefix=""):
if len(string) == 1:
storage.append(prefix + string) # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], storage, prefix+string[i])
storage = []
getPermutations("abcd", storage)
for permutation in storage: print permutation
(非効率性については気にしないでください。これは単なる例です。)
ここで、関数をジェネレーターに変換します。つまり、ストレージリストに追加するのではなく、順列を生成します。
def getPermutations(string, prefix=""):
if len(string) == 1:
yield prefix + string # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], prefix+string[i])
for permutation in getPermutations("abcd"):
print permutation
このコードは機能しません(関数は空のジェネレーターのように動作します)。
私は何かが足りないのですか?上記の再帰的アルゴリズムを反復的なものに置き換えることなくジェネレーターに変える方法はありますか?