Automate the Boring Stuff Collatz Project - python

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!

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)

Seeing as this book is a beginners guide to Python, and I am n00basF the code I wrote that got this to work is as follows:
def collatz(number):
try:
number = int(number)
while (number) != 1:
if number % 2 == 0:
number = number // 2
print(number)
elif number % 2 == 1:
number = 3 * number + 1
print(number)
else:
break
except ValueError:
print('ERROR!!! You need to enter an integer.')
print('Enter a number: ')
userNumber = input('>> ')
collatz(userNumber)

My code is below. To do the exception handling, I put it in a while loop that breaks to call the collatz function.
In my collatz function, it tests to see if the number is 1 first, then proceeds to check if the number is even or odd, and proceeds with the operation to create the new number and prints it. I call the collatz function recursively within my odd / even blocks using my new number.
def collatz(number):
if int(number) == 1:
print('')
elif int(number) % 2 == 0:
newNumber = int(number / 2)
print(newNumber)
collatz(newNumber)
elif int(number) % 2 == 1:
newNumber = int(3 * number + 1)
print(newNumber)
collatz(newNumber)
print('Enter a number:')
while True:
try:
number = int(input())
break
except ValueError:
print('Please enter a NUMBER:')
collatz(number)

Related

How to loop after 'Except ERROR' line in Python

as part of the Chapter 3 exercise for Automate the Boring Stuff, I need to write a short program that mimics the Collatz sequence, where:
If number inputted is even number, divide it by 2, repeat until it equals 1;
If number inputted is odd number, multiply it by 3 then plus 1, repeat until it equals 1;
Create a clean exit for Ctrl+C.
Detect whether the user typed in a noninteger string.
Below is my code so far, which seems to work but I would appreciate any advice/best practice for improving it.
My main question is, after the program prints 'Enter integers only', is there any short and simple way to loop back to the 'Enter any number: ' line? I can't think of anything atm besides complicated if loops. Thanks.
def collatz(number):
if number % 2 == 0 :
results = number // 2
print(results)
if results != 1:
collatz(results)
elif number % 2 == 1 :
results = 3 * number + 1
print(results)
if results != 1:
collatz(results)
try:
entry = input('Enter any number : ')
number = int(entry)
print(number)
collatz(number)
except ValueError:
print('Enter integers only.')
except KeyboardInterrupt:
sys.end()
You can try using a while loop. The below code will be helpful for you.
def collatz(number):
if number % 2 == 0 :
results = number // 2
print(results)
if results != 1:
collatz(results)
elif number % 2 == 1 :
results = 3 * number + 1
print(results)
if results != 1:
collatz(results)
while True:
try:
entry = input('Enter any number : ')
number = int(entry)
print(number)
collatz(number)
except ValueError:
print('Enter integers only.')
except KeyboardInterrupt:
break # Stop the while loop.
sys.end()
As you want to keep prompting the same, until the program exits. I'd suggest just encapsulating the program code in a while(true) loop:
while True:
try:
entry = input('Enter any number : ')
number = int(entry)
print(number)
collatz(number)
except ValueError:
print('Enter integers only.')
except KeyboardInterrupt:
sys.end()
You can define an iteration to make sure the input is integer type.
while True: # executes the loop body indefinitely
try:
entry = input('Enter any number : ')
number = int(entry)
print(number)
collatz(number)
break # immediately terminates the loop entirely
except ValueError:
print('Enter integers only.')
except KeyboardInterrupt:
sys.end()
Put it in a "while" loop.
while True:
try:
...
except:
...

Got confused about the while loops and try-except relationship in the collatz sequence

I am a starter in learning Python, and I am doing the practice project of the book called Automate the Boring Stuff with Python, chapter 3. That is a collatz sequence. My code is below:
def collatz(number):
if number % 2 == 0:
return (int(number)//2)
else:
if number % 2 ==1:
return(3*int(number)+1)
print('Enter number:')
try:
number = int(input())
while True:
if number != 1:
number = collatz(number)
print(number)
else:
break
except ValueError:
print('You must input an interger!')
This code is running well, and until the result reached 1, it stopped.like
3
10
5
16
8
4
2
1
But when I put the Try-exception block into the While loop, then everything changed. like this:
while True:
number = int(input())
try:
if number != 1:
number = collatz(number)
print(number)
else:
break
except ValueError:
print('You must input an interger!')
Then the program couldn't finish the while loop till the final result 1. It stopped after just one try, like
3
10
I can't figure it out. Could anybody here explain why? Thanks a lot!

Is there a way to go to specific line or command in python?

I am going through book automate boring stuff with python and trying to solve the practical problems.
In this project I need to define collatz() function and print results as seen in code until it gets 1.
So basically i need to input only one number and program should return numbers until it returns 1.
Program works fine but i have one question if i can make it better :D .
My question is after using try: and except: is there a way to not end process when typing string in input function but to get message below 'You must enter number' and get back to inputing new number or string and executing while loop normally. Code works fine just wondering if this is possible and if so how?
def collatz(number):
if number % 2 == 0:
print(number // 2)
return number // 2
else:
print(3 * number + 1)
return 3 * number + 1
try:
yourNumber = int(input('Enter number: '))
while True:
yourNumber = collatz(yourNumber)
if yourNumber == 1:
break
except ValueError:
print('You must enter a number')
Put the try/except inside a loop, such that on the except the loop will continue but on a success it will break:
while True:
try:
yourNumber = int(input('Enter number: '))
except ValueError:
print('You must enter a number')
else:
break
while yourNumber != 1:
yourNumber = collatz(yourNumber)

invalid syntax on int(number) on a try statement python

This is my first Project that i have to accomplish from the tutorial im currently facing.So here is the Problem i have.I am trying to use collatz(number) in order to get the collatz sequenze.I tryd to find a similar Problem on stackoverflow but nothing i could relate to (or rather me not understanding it maybe).The error occurs on the second int part.An invalid syntax error occurs on it. I checked everything i could think of(checked all spaces inbetween also changed "except" to "else" because i had trouble there) and than this problem occurred.I also tried to get another paranthese on else int((number)) %2==1: but that didn't help either. i hope you have enough information to help me out.Thank you very much for your Time.
def collatz(number):
number=input()
try:
if int(number) %2==0:
print('hi')
else int(number) %2==1:
print(int(number*3+1))
So to fix your code as described:
def collatz(number):
number = input() # number is passed in - doesn't make sense to get it again
try:
number = int(number) # Just interpret once
except ValueError: # try must have an except clause
return # exit on error
if number%2 == 0:
print('hi')
elif number%2 == 1: # Don't really need an elif - %2 can only have 2 values
print(number*3+1)
However, you may want to look into using a generator (yield):
def collatz(number):
while number > 1:
if number % 2 == 0:
number //= 2
else:
number = 3*number + 1
yield number
def collatz_series():
try:
number = int(input())
except ValueError:
return
for n in collatz(number):
print(n)

Collatz sequence ends at 4

I am writing a Collatz sequence program using the practice projects from chapter 3 of Automate the boring stuff with python.
The program outline is:
Write a function named collatz() that has one parameter named number.
If number is even, then collatz() should print number // 2 and return
this value. If number is odd, then collatz() should print and return
3 * number + 1.
Then write a program that lets the user type in an integer and that
keeps calling collatz() on that number until the function returns the
value 1.
My code runs however it stops on 4 rather than 1. For every number I have tried so far the output goes past 1 back to 4.
example output:
6,3,10,5,16,8,4,2,1,4
I am using python 3.4.2
def collatz(number):
if number % 2 == 0:
number = number //2
print(number)
return number
elif number % 2 == 1:
number = 3 * number + 1
print(number)
return number
print ("pick a number:")
while True:
try:
number = int(input())
while number != 1:
number = collatz(number)
collatz(number)
break
except ValueError:
print("Error: Please enter a valid integer")
print("Magic! You are down to 1.")
The problem is that you call collatz() once more after the loop finishes with 1. Just remove that line, and it works fine.
Also if you move the "pick a number" to the input function, you can avoid the new line after the question and are asked again every time, if you input an invalid value.
Additionally you should also check if the number is greater than or equal to 1, to avoid endless loops. The code to do all that would look like that:
while True:
try:
number = int(input("pick a number: "))
if number < 1:
print("Error: Please enter a integer greater than or equal to 1 ")
continue
while number != 1:
number = collatz(number)
# removed the additional call to collatz
break
except ValueError:
print("Error: Please enter a valid integer")
print("Magic! You are down to 1.")
def collatz(number):
number = number // 2 if number % 2 == 0 else 3 * number + 1
print(number)
return number
number = int(input("Pick a Number\n"))
while number != 1:
number = collatz(number)
print("Magic! You are down to 1.")

Categories