2

Here's a program that is intended to count the length of a Collatz sequence recursively:

def odd_collatz ( n ):
    return (3 * n) + 1

def even_collatz ( n ):
    return int(n / 2)

def collatz_counter ( initialNumber, initialLength ):
    length = initialLength

    while True:
        if initialNumber == 1:
            return length

        elif initialNumber != 1:
            length += 1

            if initialNumber % 2 == 0:
                 collatz_counter(even_collatz(initialNumber), length)

            else:
                collatz_counter(odd_collatz(initialNumber), length)

print(collatz_counter(13, 1)

The expected answer should be 10. However, the program gets stuck in an infinite loop. At the second to last step of the sequence initalNumber equals 2. The program functions as expected: collatz_counter is called using even_collatz and the number 10.

The expected action of the next step would be to run collatz_counter with an initialNumber of 1 and an initialLength of 10. What I would expect would happen is that the first if statement would evaluate to true, collatz_counter should return length and then exit. This is not, however, what happens:

What actually happens is that the function evaluates the first if statement, runs the return length line, and then jumps to the line of code under if initialNumber % 2... and the whole process repeats itself over and over and over in an infinite loop.

Any ideas as to why this might be happening?

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
superstewie
  • 71
  • 1
  • 6
  • 2
    If the initial number isn't 1, the elif and else clauses don't return anything. You're also calling a function inside itself: `collatz_counter` – Andrew Aug 20 '16 at 18:25
  • Please fix the code. It looks like you are missing some closing parenthesis in the last few lines of `collatz_counter()`. Also, as @Andrew implies, those lines should be **`return`** `collatz_counter(...)` – Warren Weckesser Aug 20 '16 at 18:29
  • I have edited it. They were typos in SE only, in the actual code they were correct. linusG gave me a heads up and I fixed them. Andrew, that's why I can't figure out what the problem is, it's evaluating things that shouldn't be evaluated. – superstewie Aug 20 '16 at 18:34
  • Now its another typo: should be ``print(collatz_counter(13, 1))``, you've missed one closing parenthesis. – linusg Aug 20 '16 at 18:38

3 Answers3

3

You are mixing recursion and looping in a bit of an odd way. The problem is while True:. Because you never return anything from within the loop there is nothing stopping it from going on forever. Your code reaches 1 then just keeps adding to the length. Here is a fixed version.

def odd_collatz ( n ):
    return (3 * n) + 1

def even_collatz ( n ):
    return int(n / 2)

def collatz_counter ( initialNumber, initialLength ):
    length = initialLength


    if initialNumber == 1:
        return length

    elif initialNumber != 1:
        length += 1

        if initialNumber % 2 == 0:
            return collatz_counter(even_collatz(initialNumber), length)

        else:
            return collatz_counter(odd_collatz(initialNumber), length)

print(collatz_counter(13, 1))
qfwfq
  • 2,416
  • 1
  • 17
  • 30
2

Looks like a typo to me. You define a function collatz_counter expecting two numbers.

But you call it like this:

...
print(collatz_counter(13), 1)

Just try to change the last line to:

print(collatz_counter(13, 1))

And it should be fine.

Hope this helps!

linusg
  • 6,289
  • 4
  • 28
  • 78
  • To piggy back off this, if `length` is defaulting to 0, it gets incremented to 1 before the function cams itself and the function will return because the length is now 1. – dckuehn Aug 20 '16 at 18:30
  • 1
    That was a typo when I typed it into here. In the program, it's written correctly. Thanks for the heads up on that! I've changed it in the OP – superstewie Aug 20 '16 at 18:31
0

The main error is the while True: loop, coupled with the missing returns.

def odd_collatz ( n ):
    return (3 * n) + 1

def even_collatz ( n ):
    return int(n / 2)

def collatz_counter(initialNumber, length):
    if initialNumber == 1:
        return length
    elif initialNumber != 1:
        length += 1
        if initialNumber % 2 == 0:
             return collatz_counter(even_collatz(initialNumber), length)
        else:
            return collatz_counter(odd_collatz(initialNumber), length)

print(collatz_counter(13, 1))

prints 10.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52