27

I'm trying to write a Collatz program using the guidelines from a project found at the end of chapter 3 of Automate the Boring Stuff with Python. I'm using python 3.4.0. Following is the project outline:

Write a function named collatz() that has one parameter named number. If the number is even, then collatz() should print number // 2 and return this value. If the 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.

The output of this program could look something like this:

Enter number: 3 10 5 16 8 4 2 1 

I am trying to make a function that uses if and elif statements within a while loop. I want the number to print, and then return to the beginning of the loop and reduce itself to one using the Collatz sequence, with each instance of a resulting number being printed as it goes through the loop. With my current code, I'm only able to print the first instance of the number, and that number does not go through the loop after that. Following is my code:

#collatz

print("enter a number:")
try:
    number = (int(input()))
except ValueError:
          print("Please enter a valid INTEGER.")


def collatz(number):
    while number != 1:

        if number % 2==0:
            number = (number//2)
            #print(number)
            return (print(int(number)))

        elif nnumber % 2==1:
            number = (3*number+1) 
            #print(number)
            return (print(int(number)))

        continue


collatz(number)
Bilesh Ganguly
  • 3,792
  • 3
  • 36
  • 58
DeltaFlyer
  • 461
  • 2
  • 8
  • 17

29 Answers29

37
def collatz(number):

    if number % 2 == 0:
        print(number // 2)
        return number // 2

    elif number % 2 == 1:
        result = 3 * number + 1
        print(result)
        return result

n = input("Give me a number: ")
while n != 1:
    n = collatz(int(n))

Output:

Give me a number: 3
10
5
16
8
4
2
1

Give me a number: 11
34
17
52
26
13
40
20
10
5
16
8
4
2
1
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Nuncjo
  • 1,290
  • 3
  • 15
  • 16
  • 2
    Two things that would make the code cleaner: `print(n)` outside `collatz` and only cast to `int` once after reading the input – WorldSEnder Jul 21 '18 at 14:59
6

Here's what I came up with:

import sys

def collatz(number):
    if number % 2 == 0:           # Even number
        result = number // 2
    elif number % 2 == 1:         # Odd number
        result = 3 * number + 1

    while result == 1:            # It would not print the number 1 without this loop
        print(result)
        sys.exit()                # So 1 is not printed forever.

    while result != 1:            # Goes through this loop until the condition in the previous one is True.
        print(result)
        number = result           # This makes it so collatz() is called with the number it has previously evaluated down to.
        return collatz(number)    

print('Enter a number: ')         # Program starts here!
try:
    number = int(input())         # ERROR! if a text string or float is input.
    collatz(number)
except ValueError:
    print('You must enter an integer type.')

                                  # Fully working!
ubundows
  • 421
  • 6
  • 11
3

Your collatz() function should print & return only the next value. (It ends when it returns.)

The while loop should not be inside the collatz() function.

You've also got inconsistent variable names (n, number, nnumber), and some important code is commented out.

Jonathan Clede
  • 126
  • 1
  • 5
  • Whoops, I played around the code and renamed the variables to 'n' from 'number' and then back to 'number' before posting. I don't know when I commented out that 'return' but I'll put it back into the code (it wasn't supposed to be commented out, if that's what you're referring to). – DeltaFlyer Nov 03 '15 at 20:50
3

My 17 lines of code for the same exercise that I have came up with.

    def collatz(number):
    """ check if the number is even or odd and performs calculations.
    """
    if number % 2  == 0: # even
        print(number // 2)
        return number //2
    elif number % 2 != 0: # odd 
        result = 3*number+1
        print(result)
        return result

try:
    n = input('Enter number: ') # takes user input
    while n !=1: # performs while loop until 'n' becomes 1
        n = collatz(int(n)) # passes 'n' to collatz() function until it arrives at '1'
except ValueError:
    print('Value Error. Please enter integer.')
Simas
  • 642
  • 8
  • 15
  • 1
    Thanks for sharing. This answer uses only the material that has been covered in the original book up to this point, and includes the try/except exception handling that are emphasized in this chapter, so I find it especially helpful. – Doc Jun 03 '20 at 19:55
1
def collatz(number):
    while number != 1:
        if number % 2 == 0:
            number = number // 2
            print(number)

        elif number % 2 == 1:
            number = number * 3 + 1
            print(number)

try:
    num = int(input())
    collatz(num)
except ValueError:
    print('Please use whole numbers only.')

This is what I came up with on my own and based solely on what I've learned from the book so far. It took me a little bit but one of the tools I used that was invaluable to me finding my solution and has also been invaluable in learning this content is the python visualizer tool at: http://www.pythontutor.com/visualize.html#mode=edit

I was able to see what my code was doing and where it was getting hung up and I was able to continually make tweaks until I got it right.

1

i am reading the same course and i made a very long solution (improving it when i learn somethign new). i suggest keeping your collatz program up to date as you progress in the chapters, its good training. mine has string manipulation and saving to a \collatzrecords.txt now!

I solved the core problem by using recursion (a method calls itself):

def autocollatz(number):
global spam                     
spam.append(number)             
if number % 2 == 0:             
    autocollatz (int(number/2))
elif number % 2 == 1 and number != 1:
    autocollatz(int(number*3+1))

spam is my list for all the values a number "sees" on its way to 1. as you can see, when the number is even the ethod is called agin with number/2. if the number is even it is called with number*3+1.

modified the number == 1 check a bit. i hope it saves calculating time - im up to 23 000 000 already! (current record is 15 733 191 with 704 steps to get it to 1)

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

try:
    chosenInt = int(input('Enter an integer greater than 1: '))

    while chosenInt < 2:
        print("Sorry, your number must be greater than 1.")
        chosenInt = int(input('Enter an integer greater than 1: '))

    print(chosenInt)

    while chosenInt != 1:
        chosenInt = collatz(chosenInt)
        print(chosenInt)

except ValueError:
    print('Sorry, you must enter an integer.')
Dylan
  • 11
  • 2
1

I managed to get it right without using any return statements and nested a while loop inside the function.

number=int(input('Enter number:\n'))

def collatz(number):

    while number !=1:
        if number% 2 == 0:
            number= number//2
            print(number)

        else:
           number=  3 * number + 1
           print(number)    


collatz(number)
1

I have added the try and except like this (with a break)

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

n = input("Give me a number: ")

while n != 1:
    try:
        isinstance(n, int)
        n = collatz(int(n))
    except:
        print('Error: Invalid argument.')
        break
0

Nuncjo got the solution that works. I tweaked it a little to add try and except statements for error handling.

def collatz(number):
    if number % 2 == 0:
        print(number // 2)
        return number // 2

    elif number % 2 == 1:
        result = 3 * number + 1
        print(result)
        return result

try:
    n = input("Enter number: ")
    while n > 0 and n!= 1:
        n = collatz(int(n))
except ValueError:
    print('whoops, type an integer, bro.')
Community
  • 1
  • 1
docgunthrop
  • 183
  • 1
  • 8
0

My Code

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

try:
    print ('Enter the number to Collatz:')
    collatz(int(input()))
except ValueError:
    print('Enter a valid integer')
Jebin
  • 1
  • 1
  • 1
    While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – zondo May 20 '16 at 10:20
0
def collatz(number):
    if number % 2 == 0:  # Even number
        return number // 2

    elif number % 2 == 1:  # Odd number
        return number * 3 + 1

print('Please enter a number') # Ask for the number


# Check if the number is an integer, if so, see if even or odd. If not, rebuke and exit
try:
    number = int(input())
    while number != 1:
        collatz(number)
        print(number)
        number = collatz(number)
    else:
        print('You Win. The number is now 1!')
except ValueError:
     print('Please enter an integer')

This is what I came up with for this practice exercise. It asks for an input Validates whether it's an integer. If not it rebukes and exits. If it is, it loops through the collatz sequence until the result is 1 and then you win.

0

Every solution on this thread is missing one thing: if the user inputs "1" the function should still run the computations of the Collatz sequence. My solution:

def collatz(number):
    while number == 1:
        print("3 * " + str(number) + " + 1 = " + str(3*number+1))
        number = 3*number+1 ##this while loop only runs once if at all b/c at end of it the value of the variable is not equal to 1
    else:
        while number != 1:
            if number % 2 == 0:
                print(str(number) + ' // 2 = ' + str(number//2))
                number = number//2
            else:
                print("3 * " + str(number) + " + 1 = " + str(3*number+1))
                number = 3*number+1

 print('Please input any integer to begin the Collatz sequence.')

while True:
    try:
        number = int(input())
        collatz(number)
        break
    except ValueError:
        print('please enter an integer')
0
def collatz(number):
    while number != 1:
        if number %2==0:
            number = number//2
            yield number
        elif number %2 ==1:
            number=number*3 +1
            yield number

while True:
    try:
        for n in collatz(int(input('Enter number:'))):
            print(n)
        break
    except ValueError:
        print('Please enter an integer')

The extra while True loop will help the program to continue functioning after the user inputs a non-integer.

0
def collatz(number): 
    if number%2==0:    
        return number//2
    elif number%2==1:
        return number*3+1
step=1 #counter variable for amusement and seeing how many steps for completion.
try: #in case of ValueError   
    number=int(input('Enter a Number for Collatz Sequencing:')) 
    while collatz(number)!=1:    
        print(collatz(number))
        number=int(collatz(number))
        if collatz(number)!=1: 
            print('Calculating step ' + str(step) + '.')
            step=step+1
        else:
            print ('Calculating step ' +str(step) + '.')
            print('1 Has Been Reached.')
except ValueError: 
     print('Enter an Integer please:')
demongolem
  • 9,474
  • 36
  • 90
  • 105
Tossaire
  • 1
  • 1
0

Here's my 19 lines:

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


number = 0
while number == 0:
    try:
        number = int(input('Please enter a number: '))
        if number == 0:
            print('Number must be an integer not equal to zero.')
        else:
            while True:
                number = collatz(number)
                print(number)
                if abs(number) == 1 or number == -5 or number == -17: 
                    break #Collatz seq ends/enters recurring loop when number hits -17, -5, -1 or 1
    except ValueError:
        print('Number must be an integer.')
toonarmycaptain
  • 2,093
  • 2
  • 18
  • 29
0

I think that this solution may be even simpler for learners than the accepted one:

def collatzSequence(number):
    if (number % 2 == 0): # if it's even
        number = number // 2
    else:                 # if it's odd
        number = number * 3 + 1
    print (number)
    return (number)

n = int(input('Enter a number: '))
while (n != 1):
    n = collatzSequence(n)

The result will something like this:

Enter a number: 5
16
8
4
2
1
Noob
  • 1,077
  • 2
  • 14
  • 16
0

14 lines:

Don't get why we need "elif number %2 == 1:" instead of simple 'else'?

def  collatz(number):
    while number != 1:
        if number %2 == 0:
            number = number/2
            print(number)
        else:
            number = 3*number+1
            print(number)
print('Enter a number')
try:
    number = (int(input()))
except ValueError:
          print("Please enter an INTEGER.")
collatz(number)
Mike K
  • 163
  • 1
  • 7
0
def cyclic(number):
    if number % 2 == 0:
        if number // 2 == 1:
            print(1)
        else:
            print(number//2)
            cyclic(number // 2)
    else:
        print((number * 3) + 1)
        cyclic((number * 3) + 1)


print("Enter a number:")
try:
    n = int(input())
    cyclic(n)
except ValueError:
    print("Unvalied value")

The simplest one

0

You can simply try this

while True:
 number=int(input('Enter next positive number or 0 to quit: '))
 iteration=0
 currentNumber=0
 item=1
 sumOfNumbers=0
 print(number,end='  ')
 if(number):
    while currentNumber !=1 :
        currentNumber=int(number/2) if(number%2==0) else number*3+1
        number=currentNumber
        iteration +=1; item +=1
        sumOfNumbers +=currentNumber
        print(currentNumber,end ='\n' if(item %5==0) else '  ')
    print('\nIt took ',iteration,'iterations to arrive at 1')
    print('The average  is ',round((sumOfNumbers/iteration),2))
 else :
    break
Ruman
  • 936
  • 11
  • 9
0
  1. In your program (question), after return statement is executed, continue is not executed. so it will loop for only one iteration.

  2. Your program will not work for input integer 1. You may want to check the result of method with 1, should not check the user input in the beginning itself. 1 is also a valid input to the program.

  3. Methods would be preferred to perform one action. (SOLID principles of programming). Better to call function in a loop rather than looping inside function. increases the reusability of the method.

def collatz(number):
    if number % 2 == 0:
        print(number // 2)              # logically, floor division is equivalent to division when even number with 2
        return number // 2
    elif number % 2 != 0:
        print(number * 3 + 1)
        return number * 3 + 1


number = int(input("Please enter a number\n"))
result = collatz(number)                # this way the program also takes 1 as input
while result != 1:
    result = collatz(result)



# Output:


Please enter a number
1
4
2
1

Please enter a number
32
16
8
4
2
1

Formatted output

Surendra
  • 25
  • 8
0

This is a perfect recursive problem, wonder why no body code it like that:

def Collatz(Num):
    if Num==1:
        return
    if Num % 2 == 1:
        newNum=int(Num*3+1)
    else:
        newNum=int(Num/2)
    print(newNum)
    Collatz(newNum)
#------------------------------------
Num = input("Enter your value: ")
try:
    val = int(Num)
    if val < 0 :
        print("Error: Please enter a positive integer only")
        exit(1)
except ValueError:
    print("Error: Please enter a positive integer only")
    exit(1)

Collatz(int(Num))
=============================================
Enter your value: 11
34
17
52
26
13
40
20
10
5
16
8
4
2
1
FEldin
  • 131
  • 7
0
import sys

def collatz(number):
    global x
    if number % 2 == 0:
        even = number // 2
        print(even)
        if even == 1:
            sys.exit()
    elif number % 2 == 1:
        odd = 3 * number + 1
        print(odd)


while True:
    try:
        x = int(input('Enter an int: '))
        collatz(x)
    except ValueError:
        print('Please input number.')
Reitei17
  • 43
  • 6
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 05 '22 at 01:16
-1
def collatz(num): 
    if num % 2: 
        return 3 * num + 1
    else:
        return num // 2

while True:
    try:
    number = int(input('Enter a positive integer.'))  
    if number <= 0: 
        continue
    break
except ValueError: 
    continue


while number != 1:
    number = collatz(number)
    print(number)
-1
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
r=''
print('Enter the number')
while r != int:
    try:
        r=input()
        while r != 1:
            r=collatz(int(r))
        break   
    except ValueError:
            print ('Please enter an integer')

I added input validation

Lukyanov Mikhail
  • 500
  • 7
  • 17
-1
def collatz(number):
    if(number%2==0):
        n=number//2
        print(n)
        return n
    else:
        ev=3*number+1
        print(ev)
        return ev
num1=input("Enter a number: \n")

try:
    num= int(num1)
    if(num==1):
        print("Enter an integer greater than 1")
    elif(num>1):
        a=collatz(num) 
        while(True):
            if(a==1):
                break
            else:
                a=collatz(a)
    else:
        print("Please, Enter a positive integer to begin the Collatz sequence")

except:
    print("please, Enter an integer")

Try to came up with a solution based on up to chapter Function from automate the boring stuff. If need help related to Collatz Problem, then visit here: http://mathworld.wolfram.com/CollatzProblem.html

-1
import sys

def collatz(number):
if number % 2 == 0:
    result = number // 2
    print (result)

elif number % 2 == 1:
    result = number * 3 + 1
    print (result)

while result == 1:
    sys.exit

while result != 1:
    number = result
    collatz(number)

print ('Enter a number')

try:
    number = int(input())
    collatz(number)

except ValueError:
    print('Please enter a valid integer')
marsaldev
  • 3,338
  • 2
  • 16
  • 27
-1

I had a hard time understanding the logic of this exercise. but I don't know what I did wrong to display the error if we have a negative number.

def collatz(number):
if number % 2 == 0:
    print(number // 2)
    return number // 2

elif number % 2 == 1:
    result = 3 * number + 1
    print(result)
    return result

while True:
try:
    entry = input('enter a positive number: ')
    while entry != 1:
        entry = collatz(int(entry))

    # if we have a negative number
    while entry < 1:
        break

except ValueError:
    print('Error, enter valid number')
  • There are multiple indentation errors in this code. Also `while entry < 1: break` doesn't make much sense (should be `if` instead of `while`). – wovano Mar 31 '22 at 17:30
-1
import sys   
result = 0   
print('key in any integer:')

def collatz():   

    number = int(input())    
    if number % 2 == 0:    
        result = number//2    
        print (result)    
        if result == 1:    
            print('finally u got it')    
            sys.exit()    
    if number % 2 == 1:    
        result = 3 * number + 1    
        print (result)

while result != 1:  
    collatz()
  • 2
    __1.__ There's no need to put the result check in the function, since your while loop is checking that anyway. __2.__ Even if the conditions are mutually exclusive, it's still better to use `elif` to show that the conditional logic is related. __3.__ There is also no need to put the user input in the function. Keep it in the loop. – General Grievance Mar 09 '22 at 14:07
  • 1
    Please explain your code as well. – Muhammad Mohsin Khan Mar 11 '22 at 11:47
  • Also `while result != 1:` is highly misleading, since `result` is initialized to 0 and never changed (the assignment inside the function creates a local variable and does not change the global variable) - the function never properly returns but exits the whole application. – wovano Mar 31 '22 at 17:26