Python - The Collatz SequenceProject Euler #14 (Longest Collatz sequence)Project Euler #14 — longest Collatz sequenceHailstone Sequences in PythonPython program for testing the Collatz ConjectureProject Euler: Longest Collatz SequenceCounting terms in Collatz sequences until 1 is reached or a limit is exceededAutomate the Boring Stuff - Collatz ExerciseComputational verification of Collatz conjecture

Can planetary bodies have a second axis of rotation?

How do rulers get rich from war?

Is there an in-universe reason Harry says this or is this simply a Rowling mistake?

Asking an expert in your field that you have never met to review your manuscript

Gas leaking in base of new gas range?

Norwegian refuses EU delay (4.7 hours) compensation because it turned out there was nothing wrong with the aircraft

Repeat elements in list, but the number of times each element is repeated is provided by a separate list

How to create a grid following points in QGIS?

Social leper versus social leopard

Where Does VDD+0.3V Input Limit Come From on IC chips?

In a jam session, when asked which key my non-transposing instrument (like a violin) is in, what do I answer?

Hiking with a mule or two?

Pseudo Game of Cups in Python

What can a pilot do if an air traffic controller is incapacitated?

Can Northern Ireland's border issue be solved by repartition?

Nanomachines exist that enable Axolotl-levels of regeneration - So how can crippling injuries exist as well?

How to reference parameters outside of Apex Class that can be configured by Administrator

US entry with tourist visa but past alcohol arrest

How does one calculate the distribution of the Matt Colville way of rolling stats?

Minimize taxes now that I earn more

How do I extract code from an arduino?

Hilbert's hotel, why can't I repeat it infinitely many times?

Cheap antenna for new HF HAM

How could artificial intelligence harm us?



Python - The Collatz Sequence


Project Euler #14 (Longest Collatz sequence)Project Euler #14 — longest Collatz sequenceHailstone Sequences in PythonPython program for testing the Collatz ConjectureProject Euler: Longest Collatz SequenceCounting terms in Collatz sequences until 1 is reached or a limit is exceededAutomate the Boring Stuff - Collatz ExerciseComputational verification of Collatz conjecture






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








5












$begingroup$


Can I get a review of my code for the the Collatz Sequence from Chapter three of Automate the Boring Stuff with Python?




The Collatz Sequence



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. (Amazingly enough, this sequence actually works for any
integer—sooner or later, using this sequence, you’ll arrive at 1! Even
mathematicians aren’t sure why. Your program is exploring what’s
called the Collatz sequence, sometimes called “the simplest impossible
math problem.”)



Remember to convert the return value from input() to an integer with
the int() function; otherwise, it will be a string value.



Hint: An integer number is even if number % 2 == 0, and it’s odd if
number % 2 == 1.



The output of this program could look something like this:



Enter number:
3
10
5
16
8
4
2
1


Input Validation



Add try and except statements to the previous project to detect
whether the user types in a noninteger string. Normally, the int()
function will raise a ValueError error if it is passed a noninteger
string, as in int('puppy'). In the except clause, print a message to
the user saying they must enter an integer.




I am mainly wondering if there is a cleaner way to write my solution.



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

def getNum():
global num
num = (input("> "))
try:
num = int(num)
except ValueError:
print('plese enter a number')
getNum()
getNum()
collatz(num)









share|improve this question









New contributor



cyberprogrammer is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$









  • 2




    $begingroup$
    Please add some description indicating what this chapter 3 thing is recommending with examples of input and output, nobody's going to guess what that is
    $endgroup$
    – Emad Boctor
    8 hours ago










  • $begingroup$
    @Edmad Broctor and @ Carcigenicate Thanks for your feedback. I went ahead and revised my post.
    $endgroup$
    – cyberprogrammer
    8 hours ago

















5












$begingroup$


Can I get a review of my code for the the Collatz Sequence from Chapter three of Automate the Boring Stuff with Python?




The Collatz Sequence



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. (Amazingly enough, this sequence actually works for any
integer—sooner or later, using this sequence, you’ll arrive at 1! Even
mathematicians aren’t sure why. Your program is exploring what’s
called the Collatz sequence, sometimes called “the simplest impossible
math problem.”)



Remember to convert the return value from input() to an integer with
the int() function; otherwise, it will be a string value.



Hint: An integer number is even if number % 2 == 0, and it’s odd if
number % 2 == 1.



The output of this program could look something like this:



Enter number:
3
10
5
16
8
4
2
1


Input Validation



Add try and except statements to the previous project to detect
whether the user types in a noninteger string. Normally, the int()
function will raise a ValueError error if it is passed a noninteger
string, as in int('puppy'). In the except clause, print a message to
the user saying they must enter an integer.




I am mainly wondering if there is a cleaner way to write my solution.



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

def getNum():
global num
num = (input("> "))
try:
num = int(num)
except ValueError:
print('plese enter a number')
getNum()
getNum()
collatz(num)









share|improve this question









New contributor



cyberprogrammer is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$









  • 2




    $begingroup$
    Please add some description indicating what this chapter 3 thing is recommending with examples of input and output, nobody's going to guess what that is
    $endgroup$
    – Emad Boctor
    8 hours ago










  • $begingroup$
    @Edmad Broctor and @ Carcigenicate Thanks for your feedback. I went ahead and revised my post.
    $endgroup$
    – cyberprogrammer
    8 hours ago













5












5








5





$begingroup$


Can I get a review of my code for the the Collatz Sequence from Chapter three of Automate the Boring Stuff with Python?




The Collatz Sequence



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. (Amazingly enough, this sequence actually works for any
integer—sooner or later, using this sequence, you’ll arrive at 1! Even
mathematicians aren’t sure why. Your program is exploring what’s
called the Collatz sequence, sometimes called “the simplest impossible
math problem.”)



Remember to convert the return value from input() to an integer with
the int() function; otherwise, it will be a string value.



Hint: An integer number is even if number % 2 == 0, and it’s odd if
number % 2 == 1.



The output of this program could look something like this:



Enter number:
3
10
5
16
8
4
2
1


Input Validation



Add try and except statements to the previous project to detect
whether the user types in a noninteger string. Normally, the int()
function will raise a ValueError error if it is passed a noninteger
string, as in int('puppy'). In the except clause, print a message to
the user saying they must enter an integer.




I am mainly wondering if there is a cleaner way to write my solution.



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

def getNum():
global num
num = (input("> "))
try:
num = int(num)
except ValueError:
print('plese enter a number')
getNum()
getNum()
collatz(num)









share|improve this question









New contributor



cyberprogrammer is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$




Can I get a review of my code for the the Collatz Sequence from Chapter three of Automate the Boring Stuff with Python?




The Collatz Sequence



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. (Amazingly enough, this sequence actually works for any
integer—sooner or later, using this sequence, you’ll arrive at 1! Even
mathematicians aren’t sure why. Your program is exploring what’s
called the Collatz sequence, sometimes called “the simplest impossible
math problem.”)



Remember to convert the return value from input() to an integer with
the int() function; otherwise, it will be a string value.



Hint: An integer number is even if number % 2 == 0, and it’s odd if
number % 2 == 1.



The output of this program could look something like this:



Enter number:
3
10
5
16
8
4
2
1


Input Validation



Add try and except statements to the previous project to detect
whether the user types in a noninteger string. Normally, the int()
function will raise a ValueError error if it is passed a noninteger
string, as in int('puppy'). In the except clause, print a message to
the user saying they must enter an integer.




I am mainly wondering if there is a cleaner way to write my solution.



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

def getNum():
global num
num = (input("> "))
try:
num = int(num)
except ValueError:
print('plese enter a number')
getNum()
getNum()
collatz(num)






python collatz-sequence






share|improve this question









New contributor



cyberprogrammer is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question









New contributor



cyberprogrammer is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question








edited 7 hours ago









200_success

136k21 gold badges175 silver badges445 bronze badges




136k21 gold badges175 silver badges445 bronze badges






New contributor



cyberprogrammer is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked 8 hours ago









cyberprogrammercyberprogrammer

266 bronze badges




266 bronze badges




New contributor



cyberprogrammer is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




cyberprogrammer is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • 2




    $begingroup$
    Please add some description indicating what this chapter 3 thing is recommending with examples of input and output, nobody's going to guess what that is
    $endgroup$
    – Emad Boctor
    8 hours ago










  • $begingroup$
    @Edmad Broctor and @ Carcigenicate Thanks for your feedback. I went ahead and revised my post.
    $endgroup$
    – cyberprogrammer
    8 hours ago












  • 2




    $begingroup$
    Please add some description indicating what this chapter 3 thing is recommending with examples of input and output, nobody's going to guess what that is
    $endgroup$
    – Emad Boctor
    8 hours ago










  • $begingroup$
    @Edmad Broctor and @ Carcigenicate Thanks for your feedback. I went ahead and revised my post.
    $endgroup$
    – cyberprogrammer
    8 hours ago







2




2




$begingroup$
Please add some description indicating what this chapter 3 thing is recommending with examples of input and output, nobody's going to guess what that is
$endgroup$
– Emad Boctor
8 hours ago




$begingroup$
Please add some description indicating what this chapter 3 thing is recommending with examples of input and output, nobody's going to guess what that is
$endgroup$
– Emad Boctor
8 hours ago












$begingroup$
@Edmad Broctor and @ Carcigenicate Thanks for your feedback. I went ahead and revised my post.
$endgroup$
– cyberprogrammer
8 hours ago




$begingroup$
@Edmad Broctor and @ Carcigenicate Thanks for your feedback. I went ahead and revised my post.
$endgroup$
– cyberprogrammer
8 hours ago










2 Answers
2






active

oldest

votes


















6














$begingroup$

Prompt



The most obvious bad practice here is the use of a global variable. Instead of setting num as a side-effect, your function should return the result.



getNum() is not such a good name for the function. PEP 8, the official style guide for Python, says that function names should be lower_case_with_underscores. Furthermore, "get" implies that the function is retrieving a piece of data that is already stored somewhere, which is not the case here. Finally, "Num" should be more specific.



The use of recursion is not appropriate. If you want a loop, write a loop.



def ask_integer():
"""
Return an integer entered by the user (repeatedly prompting if
the input is not a valid integer).
"""
while True:
try:
return int(input("> "))
except ValueError:
print("Please enter an integer")

num = ask_integer()



collatz function



Strictly speaking, you didn't follow the instructions. Your solution isn't wrong or bad — you just didn't implement the collatz function according to the specification that was given, which says that you should print and return one single number.



def collatz(num):
"""
Given a number, print and return its successor in the Collatz sequence.
"""
next = num // 2 if num % 2 == 0 else 3 * num + 1
print(next)
return next

num = ask_integer()
while num > 1:
num = collatz(num)





share|improve this answer









$endgroup$














  • $begingroup$
    Perhaps reverse the test and eliminate the comparison to 0: next = 3 * num + 1 if num % 2 else num // 2
    $endgroup$
    – RootTwo
    6 hours ago










  • $begingroup$
    @RootTwo Honestly, I find that that muddies the intent. We're not checking if num % 2 is falsey; it's not a predicate. We're checking if it's equal to 0. It just so happens that they're equivalent in Python.
    $endgroup$
    – Carcigenicate
    4 hours ago


















4














$begingroup$

First, note how you're duplicating calculations:



print(num//2)
num = num //2


This may not cause issues with this specific code, but it isn't a good practice. You're doing twice as much work as you need to, which can cause performance issues once you start writing more complicated code. Do the calculation once, and save the result. In this case though, all you need to do is reverse those lines and use num:



num = num // 2
print(num)


Also, make sure you have proper spacing around operators, and be consistent.




Your if and elif cases are exclusive of each other, and your else should never happen. If the first condition is true, then other must be false and vice-versa. There's no need for the second check. Once rewritten, you'll see that printing in every case isn't necessary. You can just print after:



while num > 1:
if num % 2 == 0:
num = num // 2

else:
num = 3 * num + 1

print(num)


Since you're just reassinging num one of two options based on a condition, a conditional expression can be used here cleanly as well:



while num > 1:
num = (num // 2) if num % 2 == 0 else (3 * num + 1)
print(num)


The braces aren't necessary, but I think they're useful here due to the number of operators involved.





Printing the numbers isn't ideal here. In most code, you need to be able to use the data that you produce. If you wanted to analyze the produced sequence, you would have to do something intercept the stdout, which is expensive and overly complicated. Make it a function that accumulates and returns a list. In the following examples, I also added some type hints to make it clearer what the type of the data is:



from typing import List

def collatz(starting_num: int) -> List[int]:
nums = [starting_num]

num = starting_num
while num > 1:
num = (num // 2) if num % 2 == 0 else (3 * num + 1)
nums.append(num)

return nums


Or, a much cleaner approach is to make it a generator that yields the numbers:



# Calling this function returns a generator that produces ints
# Ignore the two Nones, as they aren't needed for this kind of generator
def collatz_gen(starting_num: int) -> Generator[int, None, None]:
yield starting_num

num = starting_num
while num > 1:
num = (num // 2) if num % 2 == 0 else (3 * num + 1)
yield num

>>> list(collatz_gen(5))
[5, 16, 8, 4, 2, 1]




There's a few notable things about getNum:



Python uses "snake_case", not "camelCase".




Your use of global num here is unnecessary and confusing. Just like before, explicitly return any data that the function produces:



def get_num() -> int:
raw_num = input("> ")

try:
return int(raw_num)

except ValueError:
print('Please enter a number')
return get_num()


Note how instead of reassigning a global num, we're just returning the number. I also spaced things out a bit, and used some more appropriate names. Conceptually, I'd say that num = input("> ") is wrong. At the time that that runs, num does not contain a number (it contains a string).




This isn't a good use of recursion. It likely won't cause you any problems, but if your user is really dumb and enters wrong data ~1000 times, your program will crash. Just use a loop:



def get_num() -> int:
while True:
raw_num = input("> ")

try:
return int(raw_num)

except ValueError:
print('Please enter a number')


In languages like Python, be careful using recursion in cases where you have no guarantees about how many times the function will recurse.




I'd also probably name this something closer to ask_for_num. "get" doesn't make it very clear about where the data is coming from.





Taken altogether, you'll end up with:



from typing import Generator

def collatz_gen(starting_num: int) -> Generator[int, None, None]:
yield starting_num

num = starting_num
while num > 1:
num = (num // 2) if num % 2 == 0 else (3 * num + 1)
yield num

def ask_for_num() -> int:
while True:
raw_num = input("> ")

try:
return int(raw_num)

except ValueError:
print('Please enter a number')


Which can be used like:



num = ask_for_num()

for n in collatz_gen(num):
print(n)





share|improve this answer











$endgroup$

















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );







    cyberprogrammer is a new contributor. Be nice, and check out our Code of Conduct.









    draft saved

    draft discarded
















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229270%2fpython-the-collatz-sequence%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    6














    $begingroup$

    Prompt



    The most obvious bad practice here is the use of a global variable. Instead of setting num as a side-effect, your function should return the result.



    getNum() is not such a good name for the function. PEP 8, the official style guide for Python, says that function names should be lower_case_with_underscores. Furthermore, "get" implies that the function is retrieving a piece of data that is already stored somewhere, which is not the case here. Finally, "Num" should be more specific.



    The use of recursion is not appropriate. If you want a loop, write a loop.



    def ask_integer():
    """
    Return an integer entered by the user (repeatedly prompting if
    the input is not a valid integer).
    """
    while True:
    try:
    return int(input("> "))
    except ValueError:
    print("Please enter an integer")

    num = ask_integer()



    collatz function



    Strictly speaking, you didn't follow the instructions. Your solution isn't wrong or bad — you just didn't implement the collatz function according to the specification that was given, which says that you should print and return one single number.



    def collatz(num):
    """
    Given a number, print and return its successor in the Collatz sequence.
    """
    next = num // 2 if num % 2 == 0 else 3 * num + 1
    print(next)
    return next

    num = ask_integer()
    while num > 1:
    num = collatz(num)





    share|improve this answer









    $endgroup$














    • $begingroup$
      Perhaps reverse the test and eliminate the comparison to 0: next = 3 * num + 1 if num % 2 else num // 2
      $endgroup$
      – RootTwo
      6 hours ago










    • $begingroup$
      @RootTwo Honestly, I find that that muddies the intent. We're not checking if num % 2 is falsey; it's not a predicate. We're checking if it's equal to 0. It just so happens that they're equivalent in Python.
      $endgroup$
      – Carcigenicate
      4 hours ago















    6














    $begingroup$

    Prompt



    The most obvious bad practice here is the use of a global variable. Instead of setting num as a side-effect, your function should return the result.



    getNum() is not such a good name for the function. PEP 8, the official style guide for Python, says that function names should be lower_case_with_underscores. Furthermore, "get" implies that the function is retrieving a piece of data that is already stored somewhere, which is not the case here. Finally, "Num" should be more specific.



    The use of recursion is not appropriate. If you want a loop, write a loop.



    def ask_integer():
    """
    Return an integer entered by the user (repeatedly prompting if
    the input is not a valid integer).
    """
    while True:
    try:
    return int(input("> "))
    except ValueError:
    print("Please enter an integer")

    num = ask_integer()



    collatz function



    Strictly speaking, you didn't follow the instructions. Your solution isn't wrong or bad — you just didn't implement the collatz function according to the specification that was given, which says that you should print and return one single number.



    def collatz(num):
    """
    Given a number, print and return its successor in the Collatz sequence.
    """
    next = num // 2 if num % 2 == 0 else 3 * num + 1
    print(next)
    return next

    num = ask_integer()
    while num > 1:
    num = collatz(num)





    share|improve this answer









    $endgroup$














    • $begingroup$
      Perhaps reverse the test and eliminate the comparison to 0: next = 3 * num + 1 if num % 2 else num // 2
      $endgroup$
      – RootTwo
      6 hours ago










    • $begingroup$
      @RootTwo Honestly, I find that that muddies the intent. We're not checking if num % 2 is falsey; it's not a predicate. We're checking if it's equal to 0. It just so happens that they're equivalent in Python.
      $endgroup$
      – Carcigenicate
      4 hours ago













    6














    6










    6







    $begingroup$

    Prompt



    The most obvious bad practice here is the use of a global variable. Instead of setting num as a side-effect, your function should return the result.



    getNum() is not such a good name for the function. PEP 8, the official style guide for Python, says that function names should be lower_case_with_underscores. Furthermore, "get" implies that the function is retrieving a piece of data that is already stored somewhere, which is not the case here. Finally, "Num" should be more specific.



    The use of recursion is not appropriate. If you want a loop, write a loop.



    def ask_integer():
    """
    Return an integer entered by the user (repeatedly prompting if
    the input is not a valid integer).
    """
    while True:
    try:
    return int(input("> "))
    except ValueError:
    print("Please enter an integer")

    num = ask_integer()



    collatz function



    Strictly speaking, you didn't follow the instructions. Your solution isn't wrong or bad — you just didn't implement the collatz function according to the specification that was given, which says that you should print and return one single number.



    def collatz(num):
    """
    Given a number, print and return its successor in the Collatz sequence.
    """
    next = num // 2 if num % 2 == 0 else 3 * num + 1
    print(next)
    return next

    num = ask_integer()
    while num > 1:
    num = collatz(num)





    share|improve this answer









    $endgroup$



    Prompt



    The most obvious bad practice here is the use of a global variable. Instead of setting num as a side-effect, your function should return the result.



    getNum() is not such a good name for the function. PEP 8, the official style guide for Python, says that function names should be lower_case_with_underscores. Furthermore, "get" implies that the function is retrieving a piece of data that is already stored somewhere, which is not the case here. Finally, "Num" should be more specific.



    The use of recursion is not appropriate. If you want a loop, write a loop.



    def ask_integer():
    """
    Return an integer entered by the user (repeatedly prompting if
    the input is not a valid integer).
    """
    while True:
    try:
    return int(input("> "))
    except ValueError:
    print("Please enter an integer")

    num = ask_integer()



    collatz function



    Strictly speaking, you didn't follow the instructions. Your solution isn't wrong or bad — you just didn't implement the collatz function according to the specification that was given, which says that you should print and return one single number.



    def collatz(num):
    """
    Given a number, print and return its successor in the Collatz sequence.
    """
    next = num // 2 if num % 2 == 0 else 3 * num + 1
    print(next)
    return next

    num = ask_integer()
    while num > 1:
    num = collatz(num)






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 7 hours ago









    200_success200_success

    136k21 gold badges175 silver badges445 bronze badges




    136k21 gold badges175 silver badges445 bronze badges














    • $begingroup$
      Perhaps reverse the test and eliminate the comparison to 0: next = 3 * num + 1 if num % 2 else num // 2
      $endgroup$
      – RootTwo
      6 hours ago










    • $begingroup$
      @RootTwo Honestly, I find that that muddies the intent. We're not checking if num % 2 is falsey; it's not a predicate. We're checking if it's equal to 0. It just so happens that they're equivalent in Python.
      $endgroup$
      – Carcigenicate
      4 hours ago
















    • $begingroup$
      Perhaps reverse the test and eliminate the comparison to 0: next = 3 * num + 1 if num % 2 else num // 2
      $endgroup$
      – RootTwo
      6 hours ago










    • $begingroup$
      @RootTwo Honestly, I find that that muddies the intent. We're not checking if num % 2 is falsey; it's not a predicate. We're checking if it's equal to 0. It just so happens that they're equivalent in Python.
      $endgroup$
      – Carcigenicate
      4 hours ago















    $begingroup$
    Perhaps reverse the test and eliminate the comparison to 0: next = 3 * num + 1 if num % 2 else num // 2
    $endgroup$
    – RootTwo
    6 hours ago




    $begingroup$
    Perhaps reverse the test and eliminate the comparison to 0: next = 3 * num + 1 if num % 2 else num // 2
    $endgroup$
    – RootTwo
    6 hours ago












    $begingroup$
    @RootTwo Honestly, I find that that muddies the intent. We're not checking if num % 2 is falsey; it's not a predicate. We're checking if it's equal to 0. It just so happens that they're equivalent in Python.
    $endgroup$
    – Carcigenicate
    4 hours ago




    $begingroup$
    @RootTwo Honestly, I find that that muddies the intent. We're not checking if num % 2 is falsey; it's not a predicate. We're checking if it's equal to 0. It just so happens that they're equivalent in Python.
    $endgroup$
    – Carcigenicate
    4 hours ago













    4














    $begingroup$

    First, note how you're duplicating calculations:



    print(num//2)
    num = num //2


    This may not cause issues with this specific code, but it isn't a good practice. You're doing twice as much work as you need to, which can cause performance issues once you start writing more complicated code. Do the calculation once, and save the result. In this case though, all you need to do is reverse those lines and use num:



    num = num // 2
    print(num)


    Also, make sure you have proper spacing around operators, and be consistent.




    Your if and elif cases are exclusive of each other, and your else should never happen. If the first condition is true, then other must be false and vice-versa. There's no need for the second check. Once rewritten, you'll see that printing in every case isn't necessary. You can just print after:



    while num > 1:
    if num % 2 == 0:
    num = num // 2

    else:
    num = 3 * num + 1

    print(num)


    Since you're just reassinging num one of two options based on a condition, a conditional expression can be used here cleanly as well:



    while num > 1:
    num = (num // 2) if num % 2 == 0 else (3 * num + 1)
    print(num)


    The braces aren't necessary, but I think they're useful here due to the number of operators involved.





    Printing the numbers isn't ideal here. In most code, you need to be able to use the data that you produce. If you wanted to analyze the produced sequence, you would have to do something intercept the stdout, which is expensive and overly complicated. Make it a function that accumulates and returns a list. In the following examples, I also added some type hints to make it clearer what the type of the data is:



    from typing import List

    def collatz(starting_num: int) -> List[int]:
    nums = [starting_num]

    num = starting_num
    while num > 1:
    num = (num // 2) if num % 2 == 0 else (3 * num + 1)
    nums.append(num)

    return nums


    Or, a much cleaner approach is to make it a generator that yields the numbers:



    # Calling this function returns a generator that produces ints
    # Ignore the two Nones, as they aren't needed for this kind of generator
    def collatz_gen(starting_num: int) -> Generator[int, None, None]:
    yield starting_num

    num = starting_num
    while num > 1:
    num = (num // 2) if num % 2 == 0 else (3 * num + 1)
    yield num

    >>> list(collatz_gen(5))
    [5, 16, 8, 4, 2, 1]




    There's a few notable things about getNum:



    Python uses "snake_case", not "camelCase".




    Your use of global num here is unnecessary and confusing. Just like before, explicitly return any data that the function produces:



    def get_num() -> int:
    raw_num = input("> ")

    try:
    return int(raw_num)

    except ValueError:
    print('Please enter a number')
    return get_num()


    Note how instead of reassigning a global num, we're just returning the number. I also spaced things out a bit, and used some more appropriate names. Conceptually, I'd say that num = input("> ") is wrong. At the time that that runs, num does not contain a number (it contains a string).




    This isn't a good use of recursion. It likely won't cause you any problems, but if your user is really dumb and enters wrong data ~1000 times, your program will crash. Just use a loop:



    def get_num() -> int:
    while True:
    raw_num = input("> ")

    try:
    return int(raw_num)

    except ValueError:
    print('Please enter a number')


    In languages like Python, be careful using recursion in cases where you have no guarantees about how many times the function will recurse.




    I'd also probably name this something closer to ask_for_num. "get" doesn't make it very clear about where the data is coming from.





    Taken altogether, you'll end up with:



    from typing import Generator

    def collatz_gen(starting_num: int) -> Generator[int, None, None]:
    yield starting_num

    num = starting_num
    while num > 1:
    num = (num // 2) if num % 2 == 0 else (3 * num + 1)
    yield num

    def ask_for_num() -> int:
    while True:
    raw_num = input("> ")

    try:
    return int(raw_num)

    except ValueError:
    print('Please enter a number')


    Which can be used like:



    num = ask_for_num()

    for n in collatz_gen(num):
    print(n)





    share|improve this answer











    $endgroup$



















      4














      $begingroup$

      First, note how you're duplicating calculations:



      print(num//2)
      num = num //2


      This may not cause issues with this specific code, but it isn't a good practice. You're doing twice as much work as you need to, which can cause performance issues once you start writing more complicated code. Do the calculation once, and save the result. In this case though, all you need to do is reverse those lines and use num:



      num = num // 2
      print(num)


      Also, make sure you have proper spacing around operators, and be consistent.




      Your if and elif cases are exclusive of each other, and your else should never happen. If the first condition is true, then other must be false and vice-versa. There's no need for the second check. Once rewritten, you'll see that printing in every case isn't necessary. You can just print after:



      while num > 1:
      if num % 2 == 0:
      num = num // 2

      else:
      num = 3 * num + 1

      print(num)


      Since you're just reassinging num one of two options based on a condition, a conditional expression can be used here cleanly as well:



      while num > 1:
      num = (num // 2) if num % 2 == 0 else (3 * num + 1)
      print(num)


      The braces aren't necessary, but I think they're useful here due to the number of operators involved.





      Printing the numbers isn't ideal here. In most code, you need to be able to use the data that you produce. If you wanted to analyze the produced sequence, you would have to do something intercept the stdout, which is expensive and overly complicated. Make it a function that accumulates and returns a list. In the following examples, I also added some type hints to make it clearer what the type of the data is:



      from typing import List

      def collatz(starting_num: int) -> List[int]:
      nums = [starting_num]

      num = starting_num
      while num > 1:
      num = (num // 2) if num % 2 == 0 else (3 * num + 1)
      nums.append(num)

      return nums


      Or, a much cleaner approach is to make it a generator that yields the numbers:



      # Calling this function returns a generator that produces ints
      # Ignore the two Nones, as they aren't needed for this kind of generator
      def collatz_gen(starting_num: int) -> Generator[int, None, None]:
      yield starting_num

      num = starting_num
      while num > 1:
      num = (num // 2) if num % 2 == 0 else (3 * num + 1)
      yield num

      >>> list(collatz_gen(5))
      [5, 16, 8, 4, 2, 1]




      There's a few notable things about getNum:



      Python uses "snake_case", not "camelCase".




      Your use of global num here is unnecessary and confusing. Just like before, explicitly return any data that the function produces:



      def get_num() -> int:
      raw_num = input("> ")

      try:
      return int(raw_num)

      except ValueError:
      print('Please enter a number')
      return get_num()


      Note how instead of reassigning a global num, we're just returning the number. I also spaced things out a bit, and used some more appropriate names. Conceptually, I'd say that num = input("> ") is wrong. At the time that that runs, num does not contain a number (it contains a string).




      This isn't a good use of recursion. It likely won't cause you any problems, but if your user is really dumb and enters wrong data ~1000 times, your program will crash. Just use a loop:



      def get_num() -> int:
      while True:
      raw_num = input("> ")

      try:
      return int(raw_num)

      except ValueError:
      print('Please enter a number')


      In languages like Python, be careful using recursion in cases where you have no guarantees about how many times the function will recurse.




      I'd also probably name this something closer to ask_for_num. "get" doesn't make it very clear about where the data is coming from.





      Taken altogether, you'll end up with:



      from typing import Generator

      def collatz_gen(starting_num: int) -> Generator[int, None, None]:
      yield starting_num

      num = starting_num
      while num > 1:
      num = (num // 2) if num % 2 == 0 else (3 * num + 1)
      yield num

      def ask_for_num() -> int:
      while True:
      raw_num = input("> ")

      try:
      return int(raw_num)

      except ValueError:
      print('Please enter a number')


      Which can be used like:



      num = ask_for_num()

      for n in collatz_gen(num):
      print(n)





      share|improve this answer











      $endgroup$

















        4














        4










        4







        $begingroup$

        First, note how you're duplicating calculations:



        print(num//2)
        num = num //2


        This may not cause issues with this specific code, but it isn't a good practice. You're doing twice as much work as you need to, which can cause performance issues once you start writing more complicated code. Do the calculation once, and save the result. In this case though, all you need to do is reverse those lines and use num:



        num = num // 2
        print(num)


        Also, make sure you have proper spacing around operators, and be consistent.




        Your if and elif cases are exclusive of each other, and your else should never happen. If the first condition is true, then other must be false and vice-versa. There's no need for the second check. Once rewritten, you'll see that printing in every case isn't necessary. You can just print after:



        while num > 1:
        if num % 2 == 0:
        num = num // 2

        else:
        num = 3 * num + 1

        print(num)


        Since you're just reassinging num one of two options based on a condition, a conditional expression can be used here cleanly as well:



        while num > 1:
        num = (num // 2) if num % 2 == 0 else (3 * num + 1)
        print(num)


        The braces aren't necessary, but I think they're useful here due to the number of operators involved.





        Printing the numbers isn't ideal here. In most code, you need to be able to use the data that you produce. If you wanted to analyze the produced sequence, you would have to do something intercept the stdout, which is expensive and overly complicated. Make it a function that accumulates and returns a list. In the following examples, I also added some type hints to make it clearer what the type of the data is:



        from typing import List

        def collatz(starting_num: int) -> List[int]:
        nums = [starting_num]

        num = starting_num
        while num > 1:
        num = (num // 2) if num % 2 == 0 else (3 * num + 1)
        nums.append(num)

        return nums


        Or, a much cleaner approach is to make it a generator that yields the numbers:



        # Calling this function returns a generator that produces ints
        # Ignore the two Nones, as they aren't needed for this kind of generator
        def collatz_gen(starting_num: int) -> Generator[int, None, None]:
        yield starting_num

        num = starting_num
        while num > 1:
        num = (num // 2) if num % 2 == 0 else (3 * num + 1)
        yield num

        >>> list(collatz_gen(5))
        [5, 16, 8, 4, 2, 1]




        There's a few notable things about getNum:



        Python uses "snake_case", not "camelCase".




        Your use of global num here is unnecessary and confusing. Just like before, explicitly return any data that the function produces:



        def get_num() -> int:
        raw_num = input("> ")

        try:
        return int(raw_num)

        except ValueError:
        print('Please enter a number')
        return get_num()


        Note how instead of reassigning a global num, we're just returning the number. I also spaced things out a bit, and used some more appropriate names. Conceptually, I'd say that num = input("> ") is wrong. At the time that that runs, num does not contain a number (it contains a string).




        This isn't a good use of recursion. It likely won't cause you any problems, but if your user is really dumb and enters wrong data ~1000 times, your program will crash. Just use a loop:



        def get_num() -> int:
        while True:
        raw_num = input("> ")

        try:
        return int(raw_num)

        except ValueError:
        print('Please enter a number')


        In languages like Python, be careful using recursion in cases where you have no guarantees about how many times the function will recurse.




        I'd also probably name this something closer to ask_for_num. "get" doesn't make it very clear about where the data is coming from.





        Taken altogether, you'll end up with:



        from typing import Generator

        def collatz_gen(starting_num: int) -> Generator[int, None, None]:
        yield starting_num

        num = starting_num
        while num > 1:
        num = (num // 2) if num % 2 == 0 else (3 * num + 1)
        yield num

        def ask_for_num() -> int:
        while True:
        raw_num = input("> ")

        try:
        return int(raw_num)

        except ValueError:
        print('Please enter a number')


        Which can be used like:



        num = ask_for_num()

        for n in collatz_gen(num):
        print(n)





        share|improve this answer











        $endgroup$



        First, note how you're duplicating calculations:



        print(num//2)
        num = num //2


        This may not cause issues with this specific code, but it isn't a good practice. You're doing twice as much work as you need to, which can cause performance issues once you start writing more complicated code. Do the calculation once, and save the result. In this case though, all you need to do is reverse those lines and use num:



        num = num // 2
        print(num)


        Also, make sure you have proper spacing around operators, and be consistent.




        Your if and elif cases are exclusive of each other, and your else should never happen. If the first condition is true, then other must be false and vice-versa. There's no need for the second check. Once rewritten, you'll see that printing in every case isn't necessary. You can just print after:



        while num > 1:
        if num % 2 == 0:
        num = num // 2

        else:
        num = 3 * num + 1

        print(num)


        Since you're just reassinging num one of two options based on a condition, a conditional expression can be used here cleanly as well:



        while num > 1:
        num = (num // 2) if num % 2 == 0 else (3 * num + 1)
        print(num)


        The braces aren't necessary, but I think they're useful here due to the number of operators involved.





        Printing the numbers isn't ideal here. In most code, you need to be able to use the data that you produce. If you wanted to analyze the produced sequence, you would have to do something intercept the stdout, which is expensive and overly complicated. Make it a function that accumulates and returns a list. In the following examples, I also added some type hints to make it clearer what the type of the data is:



        from typing import List

        def collatz(starting_num: int) -> List[int]:
        nums = [starting_num]

        num = starting_num
        while num > 1:
        num = (num // 2) if num % 2 == 0 else (3 * num + 1)
        nums.append(num)

        return nums


        Or, a much cleaner approach is to make it a generator that yields the numbers:



        # Calling this function returns a generator that produces ints
        # Ignore the two Nones, as they aren't needed for this kind of generator
        def collatz_gen(starting_num: int) -> Generator[int, None, None]:
        yield starting_num

        num = starting_num
        while num > 1:
        num = (num // 2) if num % 2 == 0 else (3 * num + 1)
        yield num

        >>> list(collatz_gen(5))
        [5, 16, 8, 4, 2, 1]




        There's a few notable things about getNum:



        Python uses "snake_case", not "camelCase".




        Your use of global num here is unnecessary and confusing. Just like before, explicitly return any data that the function produces:



        def get_num() -> int:
        raw_num = input("> ")

        try:
        return int(raw_num)

        except ValueError:
        print('Please enter a number')
        return get_num()


        Note how instead of reassigning a global num, we're just returning the number. I also spaced things out a bit, and used some more appropriate names. Conceptually, I'd say that num = input("> ") is wrong. At the time that that runs, num does not contain a number (it contains a string).




        This isn't a good use of recursion. It likely won't cause you any problems, but if your user is really dumb and enters wrong data ~1000 times, your program will crash. Just use a loop:



        def get_num() -> int:
        while True:
        raw_num = input("> ")

        try:
        return int(raw_num)

        except ValueError:
        print('Please enter a number')


        In languages like Python, be careful using recursion in cases where you have no guarantees about how many times the function will recurse.




        I'd also probably name this something closer to ask_for_num. "get" doesn't make it very clear about where the data is coming from.





        Taken altogether, you'll end up with:



        from typing import Generator

        def collatz_gen(starting_num: int) -> Generator[int, None, None]:
        yield starting_num

        num = starting_num
        while num > 1:
        num = (num // 2) if num % 2 == 0 else (3 * num + 1)
        yield num

        def ask_for_num() -> int:
        while True:
        raw_num = input("> ")

        try:
        return int(raw_num)

        except ValueError:
        print('Please enter a number')


        Which can be used like:



        num = ask_for_num()

        for n in collatz_gen(num):
        print(n)






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 7 hours ago

























        answered 8 hours ago









        CarcigenicateCarcigenicate

        7,2341 gold badge19 silver badges46 bronze badges




        7,2341 gold badge19 silver badges46 bronze badges
























            cyberprogrammer is a new contributor. Be nice, and check out our Code of Conduct.









            draft saved

            draft discarded

















            cyberprogrammer is a new contributor. Be nice, and check out our Code of Conduct.












            cyberprogrammer is a new contributor. Be nice, and check out our Code of Conduct.











            cyberprogrammer is a new contributor. Be nice, and check out our Code of Conduct.














            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229270%2fpython-the-collatz-sequence%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            ParseJSON using SSJSUsing AMPscript with SSJS ActivitiesHow to resubscribe a user in Marketing cloud using SSJS?Pulling Subscriber Status from Lists using SSJSRetrieving Emails using SSJSProblem in updating DE using SSJSUsing SSJS to send single email in Marketing CloudError adding EmailSendDefinition using SSJS

            Кампала Садржај Географија Географија Историја Становништво Привреда Партнерски градови Референце Спољашње везе Мени за навигацију0°11′ СГШ; 32°20′ ИГД / 0.18° СГШ; 32.34° ИГД / 0.18; 32.340°11′ СГШ; 32°20′ ИГД / 0.18° СГШ; 32.34° ИГД / 0.18; 32.34МедијиПодациЗванични веб-сајту

            19. јануар Садржај Догађаји Рођења Смрти Празници и дани сећања Види још Референце Мени за навигацијуу