ardiantovn
ardiantovn

Reputation: 55

Recursive Function-Collatz

I have made:

def collatz(b):
    l=[b]
    if b==1:
        return 1
    elif b%2==0:
        l.append(collatz(b/2))
    else:
        l.append(collatz(b*3+1))
    return l

but, the output like this:

>>>[21, [64, [32, [16, [8, [4, [2, 1]]]]]]]

how to make the output like this(with recursive function):

>>>Collatz: 21 64 32 16 8 4 2 1

Upvotes: 2

Views: 2133

Answers (2)

Padraic Cunningham
Padraic Cunningham

Reputation: 180481

As tobias already answered, you need to extend not append to get a flat list but you can use also an if/else returning [b] + collatz... to get a flat list of values returned:

def collatz(b):
    if b == 1:
        return [b]
    return [b] + collatz(b / 2) if not b % 2 else [b] + collatz(b * 3 + 1)

You can format the output however you want with a print:

In [5]: from __future__ import print_function

In [6]: print("Collatz :",*collatz(20))
Collatz : 20 10 5 16 8 4 2 1

You should probably also make sure that the input is non negative or you will end up a RuntimeError.

Upvotes: 3

tobias_k
tobias_k

Reputation: 82929

Use extend instead of append, and make sure to always return a list, to return a "flat" list:

def collatz(b):
    l=[b]
    if b==1:
        return [1]                  # wrapped in list
    elif b%2==0:
        l.extend(collatz(b/2))      # extend
    else:
        l.extend(collatz(b*3+1))    # extend
    return l

Or maybe a bit more concise:

def collatz(b):
    if b == 1:
        return [b]
    elif b%2==0:
        return [b] + collatz(b/2)
    else:
        return [b] + collatz(b*3+1)

If you want to return that Collatz: prefix, you have to use a wrapper function:

def collatz(x):
    def collatz_inner(b):
        if b == 1:
            return [b]
        elif b%2==0:
            return [b] + collatz_inner(b/2)
        else:
            return [b] + collatz_inner(b*3+1)
    return "Collatz: " + ' '.join(map(str, collatz_inner(x)))

Upvotes: 3

Related Questions