Increasing speed of Project Euler #14 - Longest Collatz Sequence I'm solving Project Euler problems and uploading my solutions to GitHub. Some of my solutions are just based on math and are thanks to that very fast, but #14 is way too slow, and I have no idea how to optimize it.

"""
Longest Collatz sequence
------------------------

The following iterative sequence is defined for the set of positive integers:
n  n/2 (n is even)
n  3n + 1 (n is odd)
Using the rule above and starting with 13, we generate the following sequence:
13  40  20  10  5  16  8  4  2  1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.
Which starting number, under one million, produces the longest chain?
NOTE: Once the chain starts the terms are allowed to go above one million.

Approach:

A function `collatz` which returns the number of terms in the chain, given it's starting position.
It goes trough the sequence, but It also remembers previous ones using a global dictionary.
Get the maximum one.
"""

collatz_counts = {}

def collatz(n):
    count = 1
    start = n
    while n!=1:
        if n in collatz_counts: 
            count += collatz_counts[n]
            break
        if n%2==0: n/=2
        else: n = 3*n+1
        count += 1

    collatz_counts[start] = count
    return count

answer = max(((collatz(i),i) for i in range(1,1000000)))
print("The starting position generating the longest sequence is {0}".format(answer[1]))
You have a bug. Try calling collatz(2) a few times and you'll see the result increment by one each time.

The source of trouble is initializing count to 1. It means you always add at least 1 to the memoized value. Note however that initializing count to 0 instead would give incorrect results when the loop terminates by the n != 1 condition.

You can avoid this bug and simplify your code at the same time: if you initialize collatz_counts to {1: 1} you can loop while n not in collatz_counts: and eliminate the if ... break.


Note also that an odd number is always followed by an even number in the sequence, so you can take two steps with  n = (n * 3 + 1) // 2



I suppose you are on Python 3 because you are using print(). Note that n/=2 is float division. n becomes a float which slows down subsequent calculations. Use n //= 2 instead.