diff --git a/maths/double_factorial.py b/maths/double_factorial.py new file mode 100644 index 000000000..3c3a28304 --- /dev/null +++ b/maths/double_factorial.py @@ -0,0 +1,60 @@ +def double_factorial_recursive(n: int) -> int: + """ + Compute double factorial using recursive method. + Recursion can be costly for large numbers. + + To learn about the theory behind this algorithm: + https://en.wikipedia.org/wiki/Double_factorial + + >>> from math import prod + >>> all(double_factorial_recursive(i) == prod(range(i, 0, -2)) for i in range(20)) + True + >>> double_factorial_recursive(0.1) + Traceback (most recent call last): + ... + ValueError: double_factorial_recursive() only accepts integral values + >>> double_factorial_recursive(-1) + Traceback (most recent call last): + ... + ValueError: double_factorial_recursive() not defined for negative values + """ + if not isinstance(n, int): + raise ValueError("double_factorial_recursive() only accepts integral values") + if n < 0: + raise ValueError("double_factorial_recursive() not defined for negative values") + return 1 if n <= 1 else n * double_factorial_recursive(n - 2) + + +def double_factorial_iterative(num: int) -> int: + """ + Compute double factorial using iterative method. + + To learn about the theory behind this algorithm: + https://en.wikipedia.org/wiki/Double_factorial + + >>> from math import prod + >>> all(double_factorial_iterative(i) == prod(range(i, 0, -2)) for i in range(20)) + True + >>> double_factorial_iterative(0.1) + Traceback (most recent call last): + ... + ValueError: double_factorial_iterative() only accepts integral values + >>> double_factorial_iterative(-1) + Traceback (most recent call last): + ... + ValueError: double_factorial_iterative() not defined for negative values + """ + if not isinstance(num, int): + raise ValueError("double_factorial_iterative() only accepts integral values") + if num < 0: + raise ValueError("double_factorial_iterative() not defined for negative values") + value = 1 + for i in range(num, 0, -2): + value *= i + return value + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/maths/double_factorial_iterative.py b/maths/double_factorial_iterative.py deleted file mode 100644 index b2b58aa04..000000000 --- a/maths/double_factorial_iterative.py +++ /dev/null @@ -1,33 +0,0 @@ -def double_factorial(num: int) -> int: - """ - Compute double factorial using iterative method. - - To learn about the theory behind this algorithm: - https://en.wikipedia.org/wiki/Double_factorial - - >>> import math - >>> all(double_factorial(i) == math.prod(range(i, 0, -2)) for i in range(20)) - True - >>> double_factorial(0.1) - Traceback (most recent call last): - ... - ValueError: double_factorial() only accepts integral values - >>> double_factorial(-1) - Traceback (most recent call last): - ... - ValueError: double_factorial() not defined for negative values - """ - if not isinstance(num, int): - raise ValueError("double_factorial() only accepts integral values") - if num < 0: - raise ValueError("double_factorial() not defined for negative values") - value = 1 - for i in range(num, 0, -2): - value *= i - return value - - -if __name__ == "__main__": - import doctest - - doctest.testmod() diff --git a/maths/double_factorial_recursive.py b/maths/double_factorial_recursive.py deleted file mode 100644 index 05c9b2968..000000000 --- a/maths/double_factorial_recursive.py +++ /dev/null @@ -1,31 +0,0 @@ -def double_factorial(n: int) -> int: - """ - Compute double factorial using recursive method. - Recursion can be costly for large numbers. - - To learn about the theory behind this algorithm: - https://en.wikipedia.org/wiki/Double_factorial - - >>> import math - >>> all(double_factorial(i) == math.prod(range(i, 0, -2)) for i in range(20)) - True - >>> double_factorial(0.1) - Traceback (most recent call last): - ... - ValueError: double_factorial() only accepts integral values - >>> double_factorial(-1) - Traceback (most recent call last): - ... - ValueError: double_factorial() not defined for negative values - """ - if not isinstance(n, int): - raise ValueError("double_factorial() only accepts integral values") - if n < 0: - raise ValueError("double_factorial() not defined for negative values") - return 1 if n <= 1 else n * double_factorial(n - 2) - - -if __name__ == "__main__": - import doctest - - doctest.testmod()