1

I am creating a collatz sequence with a recursive function below:

def collatz(n):
  if n%2 == 0:
    return int(n/2)
  else:   
    return int((3 * n)/2)

From what I understand, a recursive function is a function that basically calls itself. Below I have attempted creating the recursive function with the following:

def collatz(x):
    if x == 1:
        "Done"
    print(x)
    x = collatz(x)
    return(x)

Where essentially the variable x continues to get passed into the collatz function I defined until it gets to 1. However, every time I run the recursive function it prints 'x' repeatedly and then I get the

collatz(3)    
'RecursionError: maximum recursion depth exceeded in comparison' 

Which I understand is an infinite loop essentially. I thought by reassigning it to x to the results of the first collatz() it would return the new value and continue till it hit '1' but I can't seem to quite get there.

Any help/tips/advice would be great! Thanks!

Matt Seymour
  • 8,880
  • 7
  • 60
  • 101
Harris2018
  • 503
  • 1
  • 5
  • 13
  • You get the error because you are calling the function from within the definition - you haven't finished defining the function and you should call it from outside the function (indentation). –  Oct 08 '17 at 08:44
  • I am not quite following you explanation. Which part of the function has not been defined? I just made an edit to the original post showing where I am calling the collatz function. – Harris2018 Oct 08 '17 at 08:53
  • Typing on mobile, apologies.. you have collatz(x) inside the function collatz, hence the error. Call collatz(x) outside of the function, meaning do not indent it so as to be part of the function you are defining. –  Oct 08 '17 at 08:55
  • You will find that you have not replicated your example function. Will update when near a conputer. –  Oct 08 '17 at 08:57
  • 1
    @mikey he's obviously doing that, since if he wasn't, the error he's observing is a lack of output. – Adam Smith Oct 08 '17 at 08:58
  • I thought the whole point of recursion was to be able to iterate through a function, no? I was following this [example] (https://www.python-course.eu/recursive_functions.php) – Harris2018 Oct 08 '17 at 09:00
  • the first collatz function works and gets me the first number in the sequence, I wanted to use recursion to get all of the other numbers in the sequence and stop at 1 – Harris2018 Oct 08 '17 at 09:02
  • N.B. that the "odd" case of collatz is `3n+1`, not `3n / 2` – Adam Smith Oct 08 '17 at 09:07
  • If you step through what you see in the code you can tell there is no end. `collatz` always goes into `collatz`. `x` never decreases. – Chris Oct 08 '17 at 09:09

3 Answers3

3

Recursive functions have what's known as a "base case" and what's known as a "recursive case." The base case is when you should stop recursing and return an answer.

In this case, the base case is when x==1

def collatz(x):
    if x == 1:
        return x

and the recursive case is the rest of the time

# continuing from above
    else:
        if n % 2 == 0:
            return collatz(int(n//2))
        else:
            return collatz(n*3 / 2)  # sicut. Note that the collatz sequence
                                     # uses 3n+1 here, not 3n/2 as in the question

N.B. that I change the effective value of x in the next loop through collatz before returning the result of that new call. If you don't, and simply return collatz(x), you'll never reach your base case and recurse forever.

Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • 1
    Recursion is also something that Python does particularly poorly compared to other modern languages. It's a useful concept, but try to avoid it when possible in production code. See [this implementation](https://gist.github.com/anonymous/a0757b89f944dd938adb86955fa6e799) in haskell – Adam Smith Oct 08 '17 at 09:01
  • 1
    noted - this was more for practice/learning than anything, but I appreciate the help! – Harris2018 Oct 08 '17 at 09:14
  • @Harris2018 I realize. Recursion is quite necessary to learn to have a broader understanding of software engineering, but Python lacks certain optimizations to recursion (tail call elimination chiefly among them) that make it altogether a bad idea for any non-toy code if you can avoid it. – Adam Smith Oct 08 '17 at 09:15
  • for instances like a collatz sequence then, if I need to create another sequence following a pattern, is it better to do it through a loop and avoid the recursion? Whats best practice, I tend to work with large data sets and don't want to eat up time/memory/resources – Harris2018 Oct 08 '17 at 09:19
  • @Harris2018 definitely prefer iterative sequences to recursive ones, yes. In this case I would do something [like this](https://gist.github.com/anonymous/df43bdbbc0e7d1e260ce8fbd79e29322) – Adam Smith Oct 08 '17 at 09:22
1

@Roee Gavirel

Here is the final answer based on his answer above:

def collatz(x):
    if x == 1:
        "Done"
    elif x%2 == 0:
        x = int(x/2)
        print(x)
        collatz(x)     
    else:
        x = int((3*x)+1)
        print(x)
        collatz(x)


collatz(3)

Thanks for all the help!

Harris2018
  • 503
  • 1
  • 5
  • 13
0

You show two different implementations of the same function collatz, while you need to combine them.

def collatz(n):
    if x == 1:
        "Done"
    print(x)
    if n%2 == 0:
        collatz(int(n/2))
    else:   
        collatz(int((3 * n)/2))
Roee Gavirel
  • 18,955
  • 12
  • 67
  • 94