pythonalgorithmrecursion

Syracuse sequence using recursive python functions


the problem is as follows, we get a positive integer, we keep modifying it until we get 1, if the integer is pair we divide by 2, if impair we multiply by 3 and add 1, i was able to solve this using a while loop, but it seems i can't do it using recursion

here's the code:

def syracus(N):
    s = [N]
    if N==1:
        return s
    else: 
        if N%2==0:
            s.append(syracus(N/2))
            return s
            return syracus(N/2)
        
        elif N%2==1:
            s.append(syracus(3*N+1))
            return s
            return syracus(3*N+1)

here's the output

[15, [46, [23, [70, [35, [106, [53, [160, [80, [40, [20, [10, [5, [16, [8, [4, [2, [1]]]]]]]]]]]]]]]]]]

Solution

  • The reason you get nested lists is that you append the result from recursion. But that recursive call returns a list, so you're appending a list to a list, which introduces the nesting. Instead, use extend.

    There are a few other issues:

    So, with those corrections we get:

    def syracus(n):
        lst = [n]
        if n > 1:
            if n % 2 == 0:
                lst.extend(syracus(n // 2))
            else:
                lst.extend(syracus(3 * n +  1))
        return lst
    
    print(syracus(15))
    

    This is however creating a new list for every call of syracus. You could avoid this by first getting the list from the recursive call, and then appending N to it. At the end you'll need to reverse that result:

    def syracus(n):
        def recur(n):
            if n == 1:
                lst = []
            elif n % 2 == 0:
                lst = syracus(n // 2)
            else:
                lst = syracus(3 * n + 1)
            lst.append(n)
            return lst
    
        return recur(n)[::-1]
        
    print(syracus(15))
    

    It is however more pythonic to use a generator for this, and that way you avoid creating a list at all during the algorithm. It is then up to the caller to create the list, if that is desired.

    def syracus(n):
        yield n
        if n > 1:
            if n % 2 == 0:
                yield from syracus(n // 2)
            else:
                yield from syracus(3 * n + 1)
        
    print(list(syracus(15)))