Search code examples
pythonrecursionwhile-loop

Debugging the recursion couldn't solve my Issue


I wrote this function below in Python and I am expecting to see 4 as the result but get 2. Why is that?

Here is my function:

def persistence(n):
    if 0 <= n <= 9:
        return n
    else:
        result = 0
        counter = 0
        while True:
            result += n % 10 * persistence(n // 10)
            counter += 1
            if result > 9:
                n = result
                result = 0
                continue
            return counter

print(persistence(999))  # Output should be 4 but gives me 2

The goal of the function is to calculate how many times to multiply the digits of the number until you get to a one digit number.

For example: when given n = 999 I want the process below to happen:

// 999 -> 9 * 9 * 9 = 729
// 729 -> 7 *2 *9 = 126
// 126 -> 1 *2 *6 = 12
// 12 -> 1 * 2 = 2

See? It takes four iterations to get from 999 to 2 which is a single digit number. So I want my function to return 4 which is the number of iterations to get to a one digit number but returns 2 which is not what I have expected.

I know where the problem exactly happens. It is in the line in which I wrote result += n % 10 * persistence(n // 10). when I debug it in the first iteration, instead of giving me the number 729 (the multiplication of 9 * 9 * 9) it gives me 18. Why is that? What is wrong with my code that instead of getting 729 as the output for result in the first iteration I get 18 and therefore the value of persistence(999) is not what I expect it to be?


Solution

  • It's unclear, what your function is supposed to do, as commented.

    My best guess is that you want to multiply the digits of a number.

    • In that case, you either use recursion without a while or just iterate using a loop.
    def persistence(n):
        counter = 0
        result = 1
        while n:
            last_digit = n % 10
            result *= last_digit
            n //= 10
            counter += 1
    
        print(result)
        return counter
    
    
    print(persistence(999))
    print(persistence(9999))
    
    

    Prints

    729
    3
    6561
    4
    
    
    

    Notes:

    • The return counter in your code is inside the while loop. That's probability not what you had in mind.

    • When you write your base case in a recursive functiono, you no longer have to define an else.


    Edit

    If you want to count the number of operations until reaching one digit, we only add a few conditions:

    def persistence(n):
        if -10 < n < 10:
            return 0
        if n < 0:
            n *= -1
        counter = 0
        result = 1
        while n > 9:
            last_digit = n % 10
            result *= last_digit
            n //= 10
            counter += 1
    
        return counter
    
    
    print(persistence(999))
    print(persistence(9999))
    print(persistence(123456))
    print(persistence(1))
    
    print(persistence(-999))
    print(persistence(-9999))
    print(persistence(-123456))
    print(persistence(-1))
    
    

    Prints

    2
    3
    5
    0
    2
    3
    5
    0
    
    

    This may have a minor issue, did not check. Test it and modify it.

    def persistence(n, counter=0):
        if -10 < n < 10:
            return 0
        if n < 0:
            n *= -1
        result = 1
        while n > 9:
            last_digit = n % 10
            result *= last_digit
            n //= 10
    
        counter += 1
        if result > 9:
            return persistence(result, counter + 1)
        return counter + 1
    
    
    print(persistence(999))
    print(persistence(9999))
    print(persistence(123456))
    print(persistence(1))
    
    print(persistence(-999))
    print(persistence(-9999))
    print(persistence(-123456))
    print(persistence(-1))
    
    

    Logic

    • Your code has logic issues. Logic bugs are among the most difficult "bugs". If you want to fully understand, put a print statement in each line.

    • Another way to solve the problem is to write multiple functions, so that each function does a specific task. You don't have to write the whole algorithm in one function.