#!/usr/local/cpython-3.6/bin/python3 """Create CSV for growth of permutations and combinations.""" def factorial(n: int) -> int: """Compute the factorial of n.""" product = 1 for i in range(1, n + 1): product *= i return product def is_integer(f: float) -> bool: """Return True iff f is a whole number.""" return int(f) == f def combinations_count(n: int, k: int) -> int: """ Return number of results when choosing k values from n distinct things - order does not matter. This grows slowly, and actually starts decreasing again half way through. It's that additional factorial(k) factor in the denominator that keeps this from continuing to grow. """ result = factorial(n) / (factorial(k) * factorial(n - k)) assert is_integer(result) return int(result) def permutations_count(n: int, k: int) -> int: """ Return number of results when choosing k values from n distinct things - order matters. This grows rapidly, and is strictly nondecreasing. """ result = factorial(n) / factorial(n - k) assert is_integer(result) return int(result) def main() -> None: """Create CSV for growth of permutations and combinations.""" n = 20 print('0 <= k <= n\tcombinations (order does not matter)\tpermutations (order matters)') print('n == {}\tn! / (k! * (n - k)!)\tn! / (n - k)!'.format(n)) for k in range(0, n + 1): cc = combinations_count(n, k) # We test that n choose k == n choose (n - k) just for fun test_cc = combinations_count(n, n - k) assert cc == test_cc pc = permutations_count(n, k) print('{}\t{}\t{}'.format(k, cc, pc)) main()