Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,7 @@
* [Radix2 Fft](maths/radix2_fft.py)
* [Recursive Digit Sum](maths/recursive_digit_sum.py)
* [Remove Digit](maths/remove_digit.py)
* [Reverse Factorial Recursive](maths/reverse_factorial_recursive.py)
* [Segmented Sieve](maths/segmented_sieve.py)
* Series
* [Arithmetic](maths/series/arithmetic.py)
Expand Down
58 changes: 58 additions & 0 deletions maths/reverse_factorial_recursive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
def reverse_factorial_recursive(value: int, current_divisor: int = 1) -> int:
"""
Return x such that x! == value, otherwise return -1.

The function divides `value` by 1, 2, 3, ... recursively. If the repeated
division reduces `value` exactly to 1, the factorial root x is
(current_divisor - 1). If the division ever has a remainder, no integer x
exists and the function returns -1.

Parameters
----------
value: The positive integer to test (candidate factorial value).
current_divisor: The current divisor used while reducing `value` (default is 1).

Returns
-------
The factorial root (x) if x! == value, otherwise -1.

Examples
--------
>>> reverse_factorial_recursive(120)
5
>>> reverse_factorial_recursive(24)
4
>>> reverse_factorial_recursive(150)
-1
>>> reverse_factorial_recursive(1)
1
>>> reverse_factorial_recursive(2)
2
"""
if not isinstance(value, int):
raise TypeError("value must be an integer")
if not isinstance(current_divisor, int):
raise TypeError("current_divisor must be an integer")

if value < 1:
raise ValueError("value must be a positive integer")

# Special-case: initial call with value == 1 should return 1 (since 1! = 1).
if value == 1 and current_divisor == 1:
return 1

# If value reduced to 1 during recursion, the factorial root is divisor - 1.
if value == 1:
return current_divisor - 1

# If not divisible by the current divisor, it's not a factorial number.
if value % current_divisor != 0:
return -1

return reverse_factorial_recursive(value // current_divisor, current_divisor + 1)


if __name__ == "__main__":
from doctest import testmod

testmod()
Loading