Write a function combination
that takes two integers n
and k
and returns the number of k-Combinations for a set with n elements. This is the mathematical Combination function, equal to the binomial coefficient (See https://en.wikipedia.org/wiki/Combination for further details.)
The function must raise a ValueError
if n
or k
are negative. Because n
and k
are cardinal numbers, and represent a number of elements in a set, they should not be negative here.
0 is an allowed value for either n
or k
, since you can be choosing values from the empty set. If k
is 0, then combination
should return 1.
Also, if n
is less than k
, then the result of combination
should be 0, as per standard mathematical convention.
from functools import reduce from operator import mul def combination(n: int, k: int) -> int: """ Returns the result of the mathematical combination function (''`n` choose `k`'). See https://en.wikipedia.org/wiki/Combination for further details. :param n: the number of elements in the set :param k: the number of elements to be chosen from the set :raises ValueError: if either n or k are negative :return: how many different ways there are to choose `k` elements from a set of `n` elements; the number of `k`-combinations for a set with `n` elements. """ if k < 0: raise ValueError("k must be non-negative.") if n < 0: raise ValueError("n must be non-negative.") if n < k: return 0 total_permutations = reduce(mul, range(n, n - k, -1), 1) count_that_only_differ_by_order = reduce(mul, range(k, 0, -1), 1) return total_permutations // count_that_only_differ_by_order
class NonPositiveArgumentError(ValueError):pass- from functools import reduce
- from operator import mul
class WrongArgumentsOrderError(ValueError):passclass Compute:def __init__(self, k: int, n: int) -> None:self.n = nself.k = k- def combination(n: int, k: int) -> int:
- """
- Returns the result of the mathematical combination function
- (''`n` choose `k`'). See https://en.wikipedia.org/wiki/Combination for
- further details.
@staticmethoddef get_factorial(x) -> int:if not isinstance(x, int):raise TypeError(f"n must be of type int, not {type(x)}.")if x < 0:raise NonPositiveArgumentErrorres = 1for i in range(1, x + 1):res *= ireturn resdef get_combination(self):if not isinstance(self.k, int):raise TypeError(f"k must be of type int, not {type(self.k)}.")if not isinstance(self.n, int):raise TypeError(f"n must be of type int, not {type(self.k)}.")if self.k <= 0:raise NonPositiveArgumentError("k must be positive.")if self.n <= 0:raise NonPositiveArgumentError("n must be positive.")if self.n < self.k:raise WrongArgumentsOrderError("n must be greater than or equal to k.")else:return self.get_factorial(self.n) / (self.get_factorial(self.n - self.k) * self.get_factorial(self.k))- :param n: the number of elements in the set
- :param k: the number of elements to be chosen from the set
- :raises ValueError: if either n or k are negative
- :return: how many different ways there are to choose `k` elements from a
- set of `n` elements; the number of `k`-combinations for a set with `n`
- elements.
- """
- if k < 0:
- raise ValueError("k must be non-negative.")
- if n < 0:
- raise ValueError("n must be non-negative.")
- if n < k:
- return 0
- total_permutations = reduce(mul, range(n, n - k, -1), 1)
- count_that_only_differ_by_order = reduce(mul, range(k, 0, -1), 1)
- return total_permutations // count_that_only_differ_by_order
import codewars_test as test from solution import combination @test.describe("Example") def test_group(): @test.it("test cases") def test_case(): test.assert_equals(combination(13,1), 13) test.assert_equals(combination(76,7), 2186189400) test.assert_equals(combination(15,9), 5005) test.assert_equals(combination(201,45), 1773741968572955046169961320903759897869990480) test.assert_equals(combination(5, 0), 1) test.assert_equals(combination(5, 5), 1) test.assert_equals(combination(5, 6), 0) @test.it("Exceptions") def exceptions(): test.expect_error('', lambda:combination(-1,5), exception=ValueError) test.expect_error('', lambda:combination(1,-5), exception=ValueError)
- import codewars_test as test
from solution import *- from solution import combination
- @test.describe("Example")
- def test_group():
- @test.it("test cases")
- def test_case():
test.assert_equals(Compute(1,13).get_combination(), 13.0)test.assert_equals(Compute(7,76).get_combination(), 2186189400.0)test.assert_equals(Compute(9,15).get_combination(), 5005.0)test.assert_equals(Compute(45,201).get_combination(), 1.773741968572955e+45)- test.assert_equals(combination(13,1), 13)
- test.assert_equals(combination(76,7), 2186189400)
- test.assert_equals(combination(15,9), 5005)
- test.assert_equals(combination(201,45), 1773741968572955046169961320903759897869990480)
- test.assert_equals(combination(5, 0), 1)
- test.assert_equals(combination(5, 5), 1)
- test.assert_equals(combination(5, 6), 0)
- @test.it("Exceptions")
def exceptions():test.expect_error('', lambda:Compute(2.5, 5).get_combination(), exception=TypeError)test.expect_error('', lambda:Compute(2, '5').get_combination(), exception=TypeError)test.expect_error('', lambda:Compute(7,5).get_combination(), exception=WrongArgumentsOrderError)test.expect_error('', lambda:Compute(-1,5).get_combination(), exception=NonPositiveArgumentError)test.expect_error('', lambda:Compute(1,-5).get_combination(), exception=NonPositiveArgumentError)@test.it("Factorial test cases")def test_cases():test.assert_equals(Compute(True, True).get_factorial(0), 1)test.assert_equals(Compute(True, True).get_factorial(1), 1)test.assert_equals(Compute(True,True).get_factorial(5), 120)test.assert_equals(Compute(True, True).get_factorial(10), 3628800)@test.it("Factorial exceptions")def factorial_exceptions():test.expect_error('', lambda:Compute(True, True).get_factorial('42'), exception=TypeError)test.expect_error('', lambda:Compute(True, True).get_factorial(4.2), exception=TypeError)test.expect_error('', lambda:Compute(True, True).get_factorial(-1), exception=NonPositiveArgumentError)test.expect_error('', lambda:Compute(True, True).get_factorial(-10), exception=NonPositiveArgumentError)- def exceptions():
- test.expect_error('', lambda:combination(-1,5), exception=ValueError)
- test.expect_error('', lambda:combination(1,-5), exception=ValueError)