Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automate the Boring Stuff Collatz Project

I'm currently working on the collatz project in chapter 3 of Automate the Boring Stuff. I have a fully working collatz function for integer inputs, however I'm stuck trying to get the program to run when I add try, except statements for non-integer values.

Here is my code that only works for integer inputs:

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

print('Type in a number: ')
colNum = int(input())

while colNum != 1:
        colNum = collatz(colNum)

Now, heres my code when I add a try/except statement:

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

def integercheck(inputVal):
    try:
        return int(inputVal)
    except ValueError:
        print('Error: Input needs to be a number.')
        print('Type in a number: ')
        integercheck(input())

print('Type in a number: ')
colNum = integercheck(input())

while colNum != 1:
        colNum = collatz(colNum)

and here is the error code I recieve:

Type in a number: 
string
Error: Input needs to be a number.
Type in a number: 
string
Error: Input needs to be a number.
Type in a number: 
5
Traceback (most recent call last):
  File "/Users/Library/Preferences/PyCharmCE2018.2/scratches/scratch_1.py", line 22, in <module>
    colNum = collatz(colNum)
  File "/Users/Library/Preferences/PyCharmCE2018.2/scratches/scratch_1.py", line 3, in collatz
    if number % 2 == 0:
TypeError: unsupported operand type(s) for %: 'NoneType' and 'int'

Process finished with exit code 1

To be clear, this program works when I throw in an integer immediately, but it fails to work when I throw in an integer after I've typed in a string. If anyone could help I would appreciate it. Thank you!

like image 526
user601206 Avatar asked Oct 25 '25 18:10

user601206


1 Answers

The recursive case doesn't return anything, so control reaches the end of the function as the call stack resolves (Python functions implicitly return None, hence your error). Change the line:

integercheck(input())

to

return integercheck(input())

or avoid recursion entirely. A few additional remarks:

  • Avoid printing inside your function. This side effect makes it less reusable.
  • input("") takes a prompt string that's worth taking advantage of.
  • Use snake_case in Python per PEP8
  • collatz only does one step of the sequence, so the name is a little misleading. The burden of setting the next iteration falls on the caller, but this does give the caller some flexibility in determining what to do with intermediate values. With that in mind, this function seems like a perfect fit for refactoring to a generator, giving the ability to take elements one at a time or run the whole sequence as the calling code sees fit.

A possible rewrite:

def collatz(n):
    while n > 1:
        if n % 2 == 0:
            n //= 2
        else:
            n = 3 * n + 1

        yield n

def get_int(prompt="Enter a number: ", 
            err="Error: Input needs to be a number."):
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            print(err)

if __name__ == "__main__":
    for step in collatz(get_int()):
        print(step)
like image 192
ggorlen Avatar answered Oct 28 '25 07:10

ggorlen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!