Skip to content

Commit 92a5002

Browse files
committed
added a faster solution to project euler problem 14
1 parent 88e82db commit 92a5002

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

Diff for: project_euler/problem_14/sol3.py

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
Collatz conjecture: start with any positive integer n. Next term obtained from
5+
the previous term as follows:
6+
If the previous term is even, the next term is one half the previous term.
7+
If the previous term is odd, the next term is 3 times the previous term plus 1.
8+
The conjecture states the sequence will always reach 1 regardless of starting
9+
n.
10+
Problem Statement:
11+
The following iterative sequence is defined for the set of positive integers:
12+
n → n/2 (n is even)
13+
n → 3n + 1 (n is odd)
14+
Using the rule above and starting with 13, we generate the following sequence:
15+
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
16+
It can be seen that this sequence (starting at 13 and finishing at 1) contains
17+
10 terms. Although it has not been proved yet (Collatz Problem), it is thought
18+
that all starting numbers finish at 1.
19+
Which starting number, under one million, produces the longest chain?
20+
"""
21+
22+
23+
def solution(m):
24+
""" Returns the number under n that generates the longest Collatz sequence.
25+
26+
>>> solution(1000000)
27+
{'counter': 525, 'largest_number': 837799}
28+
>>> solution(200)
29+
{'counter': 125, 'largest_number': 171}
30+
>>> solution(5000)
31+
{'counter': 238, 'largest_number': 3711}
32+
>>> solution(15000)
33+
{'counter': 276, 'largest_number': 13255}
34+
"""
35+
# we are going to avoid repeat computations by creating a knowledge base
36+
# where we store the length of all collatz chains we calculated so far
37+
38+
knowledge = {1: 1}
39+
40+
# a single step in a collatz chain
41+
def collatz(n):
42+
if n % 2 == 0:
43+
return n // 2
44+
else:
45+
return 3 * n + 1
46+
47+
# calculates a collatz chain of a certain number this calculation is halted
48+
# whenever we find a key with a know collatz chain in our knowledge base
49+
def calculateChain(n):
50+
entries = []
51+
while n not in knowledge:
52+
entries.append(n)
53+
n = collatz(n)
54+
chainSize = knowledge[n]
55+
for i in entries[::-1]:
56+
chainSize += 1
57+
knowledge[i] = chainSize
58+
59+
maxChain = {
60+
"counter": 1,
61+
"largest_number": 1
62+
}
63+
for i in range(1, m + 1):
64+
calculateChain(i)
65+
if maxChain["counter"] < knowledge[i]:
66+
maxChain = {
67+
"counter": knowledge[i],
68+
"largest_number": i
69+
}
70+
71+
return maxChain
72+
73+
74+
if __name__ == "__main__":
75+
print("calculate the number with the longest collatz chain in the range between 1 and the following number:")
76+
inputNumber = int(input().strip())
77+
number, chainLength = solution(inputNumber)
78+
print(f"the maximum collatz chain of all numbers between 1 and {inputNumber} is {chainLength}, starting with the number {number}")
79+

0 commit comments

Comments
 (0)