Hailstone Sequence Python: Collatz Examples and Code

The hailstone sequence in Python is a compact way to practice loops, conditionals, function design, and integer reasoning. It is also called the Collatz sequence. Start with a positive integer. If the number is even, divide it by 2. If the number is odd, multiply it by 3 and add 1. Repeat those rules until the sequence reaches 1. Hailstone and Collatz are two names for the same sequence; Collatz Sequence Python: Code Examples and Steps provides a companion implementation and step trace.

The name comes from the way values can rise and fall before they settle down, like hailstones moving through a cloud. For example, starting from 7 gives 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1. The path is easy to describe, but the behavior can still surprise beginners because a small input may climb before it drops.

The official Python tutorial on if statements and for statements are useful background for these examples.

For most practical examples, use a while loop. The loop naturally says, “keep going until the current value is 1.” A function that returns a list is even better than printing inside the loop, because returned data can be tested, displayed, counted, or compared later. Recursion is possible, but it is mainly a learning exercise for this problem.

Print A Hailstone Sequence With A Loop

The shortest version keeps one current number and updates it until it reaches 1. The modulo operator checks whether the current number is even.

n = 7

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

print(1)

This prints every value in the path that starts at 7. Integer division with // is the right choice for the even step because the hailstone rule stays inside whole numbers.

Printing is fine for a first demonstration. Once you want tests or reusable code, return a list instead. That keeps the sequence logic separate from the way the result is displayed.

Return The Sequence As A List

A reusable function should accept the starting value, collect each term, and return the complete path. This makes the code easier to test and easier to use from another script.

def hailstone_sequence(start):
    if start < 1:
        raise ValueError("start must be positive")

    terms = [start]
    current = start
    while current != 1:
        if current % 2 == 0:
            current = current // 2
        else:
            current = 3 * current + 1
        terms.append(current)

    return terms

print(hailstone_sequence(10))

Starting at 10 returns [10, 5, 16, 8, 4, 2, 1]. The function raises ValueError for zero and negative inputs because the standard hailstone exercise starts with a positive integer.

This structure is a strong default. It keeps the rule readable, includes the final 1, and gives the caller full control over formatting.

Count The Number Of Steps

The stopping time is the number of updates needed to reach 1. It is one less than the number of terms in the returned list, because the starting value counts as a term but not as a step.

def hailstone_steps(start):
    if start < 1:
        raise ValueError("start must be positive")

    steps = 0
    current = start
    while current != 1:
        if current % 2 == 0:
            current = current // 2
        else:
            current = 3 * current + 1
        steps += 1

    return steps

print(hailstone_steps(7))

The result for 7 is 16. That matches the sequence shown earlier, which has seventeen terms including the start and the final 1.

Counting steps is useful when comparing starts. It avoids storing every term when the final count is all you need.

Validate Text Input Before Running

If the starting value comes from a user, convert and validate it before the hailstone function runs. Keep that input handling outside the sequence function so each piece has one job.

def hailstone_steps(start):
    if start < 1:
        raise ValueError("start must be positive")

    steps = 0
    current = start
    while current != 1:
        if current % 2 == 0:
            current = current // 2
        else:
            current = 3 * current + 1
        steps += 1

    return steps

def parse_positive_int(text):
    try:
        number = int(text)
    except ValueError:
        raise ValueError("enter a whole number") from None

    if number < 1:
        raise ValueError("enter a positive number")
    return number

start = parse_positive_int("27")
print(hailstone_steps(start))

This parser rejects blank text, decimal text, words, zero, and negative numbers. A command-line program could catch the error and print a friendly message instead of showing a traceback.

Clear validation matters because the hailstone rules are meant for positive integers. Without that boundary, invalid input can create confusing output or a loop that does not match the exercise.

Use Recursion For A Small Example

A recursive version can express the same rule by calling the function again with the next term. It is compact, but it should be reserved for small inputs and teaching recursion.

def hailstone_recursive(n):
    if n < 1:
        raise ValueError("n must be positive")
    if n == 1:
        return [1]
    if n % 2 == 0:
        return [n] + hailstone_recursive(n // 2)
    return [n] + hailstone_recursive(3 * n + 1)

print(hailstone_recursive(6))

This returns [6, 3, 10, 5, 16, 8, 4, 2, 1]. The base case is n == 1; without it, the function would keep calling itself until Python stops it.

The recursive shape is useful for learning, but a loop is safer for larger starts. Python has a recursion limit, and building many short lists with + also adds overhead.

Find The Highest Value Reached

Some starts climb high before they fall. Tracking the peak helps show that the sequence is not simply a steady countdown.

def hailstone_peak(start):
    if start < 1:
        raise ValueError("start must be positive")

    current = start
    peak = start
    while current != 1:
        if current % 2 == 0:
            current = current // 2
        else:
            current = 3 * current + 1
        peak = max(peak, current)

    return peak

print(hailstone_peak(27))

The start 27 is a classic example because it takes many steps and reaches a much larger peak before ending at 1. This makes it a good test case when checking that your implementation follows the odd and even rules correctly.

You can combine this peak function with the step counter to compare several starts. For a classroom exercise, try starts from 1 through 20 and record both the stopping time and the highest value reached.

Which Hailstone Method Should You Use?

Use the list-returning function when you need the full sequence. Use the step-counting function when you only care how long the path takes. Use the peak function when you want to study how high the path climbs. Keep recursion for short examples where the goal is to explain function calls, not to process large inputs.

Good tests should include 1, a short even start such as 6, a longer odd start such as 7, and invalid input such as 0. These cases catch the common mistakes: forgetting to include the final 1, using normal division instead of integer division, skipping validation, or counting terms instead of steps.

The Collatz conjecture says that every positive integer eventually reaches 1 under these rules, but that has not been proven for all positive integers. For Python learning, you do not need to solve the conjecture. You only need to implement the two rules clearly, validate the starting value, and choose the return shape that matches the task.

Subscribe
Notify of
guest
2 Comments
Oldest
Newest Most Voted
Bibekananda sahoo
Bibekananda sahoo
4 years ago

Can someone please explain how to solve this question by for loop

Pratik Kinage
Admin
4 years ago

Using for loop will work but it will become tricky. Is there any specific reason you want to use for loop over while loop?

Regards,
Pratik