に合わせて十分速いだろう、それは順列を取得するためにget_nth_permutation
を使用することが不要だと考えています。リストをシャッフルしてください!
>>> import random
>>> l = range(21)
>>> def random_permutations(l, n):
... while n:
... random.shuffle(l)
... yield list(l)
... n -= 1
...
>>> list(random_permutations(l, 5))
[[11, 19, 6, 10, 0, 3, 12, 7, 8, 16, 15, 5, 14, 9, 20, 2, 1, 13, 17, 18, 4],
[14, 8, 12, 3, 5, 20, 19, 13, 6, 18, 9, 16, 2, 10, 4, 1, 17, 15, 0, 7, 11],
[7, 20, 3, 8, 18, 17, 4, 11, 15, 6, 16, 1, 14, 0, 13, 5, 10, 9, 2, 19, 12],
[10, 14, 5, 17, 8, 15, 13, 0, 3, 16, 20, 18, 19, 11, 2, 9, 6, 12, 7, 4, 1],
[1, 13, 15, 18, 16, 6, 19, 8, 11, 12, 10, 20, 3, 4, 17, 0, 9, 5, 2, 7, 14]]
オッズはlen(l)
> 15とn
< 100000のため、このリストに表示されて重複に対して圧倒的ですが、あなたが、またはlen(l)
の低い値のための保証が必要な場合は、ちょうどそれはだ場合は、重複を記録し、スキップするset
を使用しますあなたのコメントで見てきたように、n
がlen(l)!
に近づくと、これはストールします。ような何か:len(l)
が長くなると、もはやとして、リストの可能な順列の数は、乱数ジェネレータの期間を超えて増加するため
def random_permutations(l, n):
pset = set()
while len(pset) < n:
random.shuffle(l)
pset.add(tuple(l))
return pset
はしかし、random.shuffle
は、信頼性の低いなります!だから、l
のすべての順列をそのように生成することはできません。その時点で、get_nth_permutation
を一連の乱数にマップするだけでなく、すべての乱数を0
とlen(l)
の間で生成できる乱数ジェネレータも必要です。比較的均一な分布である。それは、より堅牢なランダム性の源を見つける必要があるかもしれません。
しかし、いったんそれができたら、解答はMark Ransomの答えと同じくらい簡単です。
len(l)
でrandom.shuffle
が信頼できない理由を理解するには、次の点を考慮してください。 random.shuffle
は、0
とlen(l) - 1
の間の乱数を選択するだけです。しかし、それはその内部状態に基づいてそれらの番号を選び出し、有限(そして固定)の状態数しか取ることができません。同様に、渡すことができる可能なシード値の数は有限です。これは、生成することができる固有の一連の数列も有限であることを意味します。 s
と設定してください。 len(l)! > len(s)
の場合、これらの順列に対応するシーケンスはs
にないため、一部の順列は決して生成できません。
これが問題になる正確なの長さは何ですか?よく分かりません。しかし、価値があるものについては、random
で実装されているメルセンヌツイスタの期間は2**19937-1です。 shuffle docsは一般的な意味で私の意見を繰り返します。 Wikipediaの問題については、hereで何を言いたいのかも見てください。
range(len(population))にrandom.shuffleを呼び出して、以前に見たことがあるかどうかを確認することはできませんか? (できるかどうかを確認するため、[0,1]から10個の固有のサンプルを要求していないことを確認します) – DSM
興味深いです。 python3にはこの制限はありません。 '>>> range(math.factorial(10000))'も秒以内に戻ります。 "、" >>> len(range(math.factorial(10000))) 'yields:' OverflowError:Python intが大きすぎてC ssize_t ' – ch3ka
@ch3kaに変換できません。これはPython3の' range'がジェネレータを返すからです。しかし、ジェネレータを 'range'からリストに強制して(長さをチェックするために)、' OverflowError'を取得します。 @Wilduckもちろん。 – Wilduck