Following corrections allows posted code to run
- factorial has to be reset to 1 at the beginning of loop for factorial computation
- Don't use variable names that's the same as popular builtin functions (i.e. sum)
- To allow the function to be recursive we must perform Tail Call Optimization, otherwise, we quickly overcome the Python stack frame limit.
- Python doesn't provide tail call optimization out of the box, but it's easily implemented using method from Tail Recursion In Python
- Return the value of the recursive call i.e.
solution(n +1)
does not return a value
Corrections highlighted in code.
Code
#-------------------------------------------------------
# Decorator class to allow for optimized tail recursion
#-------------------------------------------------------
class Recurse(Exception):
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
def recurse(*args, **kwargs):
raise Recurse(*args, **kwargs)
def tail_recursive(f):
def decorated(*args, **kwargs):
while True:
try:
return f(*args, **kwargs)
except Recurse as r:
args = r.args
kwargs = r.kwargs
continue
return decorated
#-------------------------------------------------------
# Corrected code and revised to use tail call optimization
#-------------------------------------------------------
@tail_recursive
def solution(n):
m = str(n)
dig = map(int, m)
digits = list(dig)
sum_ = 0 # Correction: don't use sum as a variable name since it's a built-ini
for i in digits:
if i == 0:
sum_ += 1
else:
# Factorial of digit i
factorial = 1 # Correction: Reset value to 1
for i in range(1, i + 1):
factorial = factorial*i
sum_ += factorial
if sum_ == n:
return sum_
elif sum_ != n:
# Recursive call using recurse which provides tail call optimization
return recurse(n + 1)
Tests
for n in range(140, 150):
print(f'n = {n}, next strong number: {solution(n)}')
Output
n = 140, next strong number: 145
n = 141, next strong number: 145
n = 142, next strong number: 145
n = 143, next strong number: 145
n = 144, next strong number: 145
n = 145, next strong number: 145
n = 146, next strong number: 40585
n = 147, next strong number: 40585
n = 148, next strong number: 40585
n = 149, next strong number: 40585