pythonvariableswhile-loopcalling-conventioncollatz

Collatz conjecture function in Python3 calling itself when being assigned to a variable


I'm reading the book "Automate the boring stuff" by Al Sweigart to start learning Python (it is free online, so you can check it if you're interested, or you think that it would help solve my problem). And by the end of Chapter 3, you are given an exercise, creating a program that can execute the Collatz Conjecture. I've successfully created a function that takes an input integer and divides it by 2 or multiplies it by 3 and adds 1 for even and odd numbers, respectively.

The issue comes, when I try to take the value returned by the function, and assign it to a variable(so I can make a loop that will stop when the number gets to one), it instead calls the function, and when I try to use the function inside a while loop it returns a None value.

I tried comparing it to other program that simulates a magic 8-ball, because the way I made the way I made the Collatz program is very similar to the 8-ball, but somehow the 8-ball does work, and the Collatz doesn't, and since I'm currently out of ideas, I ask you if you can notice any typos in my code that may indicate why this is happening.

I thank you in advance for your time and effort. PS: don't forget to drink some water, it is good for you <3

THE CODES:

1.-Collatz(no while loop included)

import random
even = range(0, 1001, 2)


def collatz(number):
    if number in even:
        print(number // 2)
        return
    else:
        print(3 * number + 1)
        return

startNumber = int(input())
newNumber = collatz(startNumber)

2.- 8-ball

import random

def getAnswer(x):
    if x == 1:
        return 'It is certain'
    elif x == 2:
        return 'It is decidedly so'
    elif x == 3:
        return 'Yes'
    elif x == 4:
        return 'Reply hazy try again'
    elif x == 5:
        return 'Ask again later'
    elif x == 6:
        return 'Concentrate and ask again'
    elif x == 7:
        return 'My reply is no'
    elif x == 8:
        return 'Outlook not so good'
    elif x == 9:
        return 'Very doubtful'

r = random.randint(1, 9)
fortune = getAnswer(r)
print(fortune)

3.- Collatz made with the hints from the book(includes while loop)

def collatz(number):
    if number % 2 == 0:
        print(number // 2)
        return
    elif number % 2 == 1:
        print(3 * number + 1)
        return

startNumber = int(input())

while startNumber != 1:
    collatz(startNumber)
    newNumber = collatz(startNumber)
    collatz(newNumber)

Also, here's an SS of the book, just in case enter image description here


Solution

  • You have unused variables, and you need to define a return value for collatz().

    Right now, you define a variable newNumber, but never use it anywhere in your code. You should be updating startNumber instead (renamed to num below for readability). You also need to define a return value for collatz(); otherwise, it will return None, which isn’t what the question asks for.

    Here’s a solution which resolves these issues.

    def collatz(number):
        if number % 2 == 0:
            print(number // 2)
            return number // 2
        elif number % 2 == 1:
            print(3 * number + 1)
            return 3 * number + 1
    
    num = int(input())
    while num != 1:
        num = collatz(num)