問題を解決し、あなたが持っているかもしれないどんなアプリケーションにも十分に一般的である単純な解決策はこれです:
def combinations(words, length):
if length == 0:
return []
result = [[word] for word in words]
while length > 1:
new_result = []
for combo in result:
new_result.extend(combo + [word] for word in words)
result = new_result[:]
length -= 1
return result
基本的に、これはすべての組み合わせのメモリにツリーを徐々に構築し、それらを返します。ただし、メモリを大量に消費するため、大規模な組み合わせには実用的ではありません。
この問題の別の解決策は、確かにカウントを使用することですが、生成された数値を単語リストから単語のリストに変換することです。そのためには、まず関数 ( と呼ばれるnumber_to_list()
)が必要です。
def number_to_list(number, words):
list_out = []
while number:
list_out = [number % len(words)] + list_out
number = number // len(words)
return [words[n] for n in list_out]
これは実際には、10 進数を他の基数に変換するためのシステムです。次に、カウント関数を書きます。これは比較的単純で、アプリケーションのコアを構成します。
def combinations(words, length):
numbers = xrange(len(words)**length)
for number in numbers:
combo = number_to_list(number, words)
if len(combo) < length:
combo = [words[0]] * (length - len(combo)) + combo
yield combo
これは Python ジェネレーターです。ジェネレーターにすることで、使用する RAM を減らすことができます。数字を単語のリストに変換した後、少し作業が必要です。これは、これらのリストが要求された長さになるようにパディングが必要なためです。次のように使用されます。
>>> list(combinations('01', 3))
[['0', '0', '0'], ['0', '0', '1'],
['0', '1', '0'], ['0', '1', '1'],
['1', '0', '0'], ['1', '0', '1'],
['1', '1', '0'], ['1', '1', '1']]
ご覧のとおり、リストのリストが返されます。これらの各サブリストには、一連の元の単語が含まれています。次に、次のようなmap(''.join, list(combinations('01', 3)))
結果を取得することができます。
['000', '001', '010', '011', '100', '101', '110', '111']
これをディスクに書き込むことができます。ただし、より良いアイデアは、ジェネレーターに組み込まれている最適化を使用して、次のようにすることです。
fileout = open('filename.txt', 'w')
fileout.writelines(
''.join(combo) for combo in combinations('01', 3))
fileout.close()
これは、必要なだけの RAM のみを使用します (1 つの組み合わせを保存するのに十分な量)。これが役立つことを願っています。