from math import factorial from typing import Sized, Iterator def len_combinations(iterable: Sized, r: int) -> int: """How many options will itertools.combinations(iterable, r) yield?""" n = len(iterable) if r > n: return 0 else: return factorial(n) // factorial(r) // factorial(n - r) def len_permutations(iterable: Sized, r: int) -> int: """How many options will itertools.permutations(iterable, r) yield?""" n = len(iterable) if r > n: return 0 else: return factorial(n) // factorial(n - r) def combinations_of_sum(total_sum: int, length: int = None, min_value: int = 0) -> Iterator[tuple[int]]: if length is None: length = total_sum if length == 1: yield (total_sum,) else: for value in range(min_value, total_sum + 1): for permutation in combinations_of_sum(total_sum - value, length - 1, min_value): yield (value,) + permutation