順列と組み合わせをカウントするコードがいくつかあり、多数の場合にうまく機能するようにしようとしています。
大規模な中間結果を回避する順列のより良いアルゴリズムを見つけましたが、組み合わせについてはまだ改善できると思います。
これまでのところ、nCr の対称性を反映するために特別なケースを用意しましたが、不必要に大きな中間結果である factorial(r) の呼び出しを回避するより良いアルゴリズムを見つけたいと思っています。この最適化を行わないと、最後の doctest で factorial(99000) を計算するのに時間がかかりすぎます。
組み合わせを数えるより効率的な方法を提案できる人はいますか?
from math import factorial
def product(iterable):
prod = 1
for n in iterable:
prod *= n
return prod
def npr(n, r):
"""
Calculate the number of ordered permutations of r items taken from a
population of size n.
>>> npr(3, 2)
6
>>> npr(100, 20)
1303995018204712451095685346159820800000
"""
assert 0 <= r <= n
return product(range(n - r + 1, n + 1))
def ncr(n, r):
"""
Calculate the number of unordered combinations of r items taken from a
population of size n.
>>> ncr(3, 2)
3
>>> ncr(100, 20)
535983370403809682970
>>> ncr(100000, 1000) == ncr(100000, 99000)
True
"""
assert 0 <= r <= n
if r > n // 2:
r = n - r
return npr(n, r) // factorial(r)