Skip to content

Commit 1970cdf

Browse files
authored
Refactor the collatz conjecture with memoization and safety limits
1 parent 02131ee commit 1970cdf

1 file changed

Lines changed: 70 additions & 15 deletions

File tree

math/Collatz-Conjecture/Collatz-Conjecture.py

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,90 @@
88
print("- Continue until you reach 1")
99
print("=" * 50)
1010

11+
MAX_STEPS = 100000
12+
MAX_VALUE = 10**18
13+
MAX_INPUT = 10**12
14+
steps_cache = {1: 0}
15+
16+
def collatz_next(n):
17+
return n // 2 if n % 2 == 0 else 3 * n + 1
18+
19+
def get_remaining_sequence(n):
20+
seq = []
21+
while n != 1:
22+
n = collatz_next(n)
23+
seq.append(n)
24+
return seq
25+
def collatz_sequence(start):
26+
if start in steps_cache:
27+
n = start
28+
yield n
29+
while n != 1:
30+
n = collatz_next(n)
31+
yield n
32+
return
33+
34+
n = start
35+
path = [n]
36+
steps = 0
37+
38+
yield n
39+
40+
while n != 1 and steps < MAX_STEPS:
41+
n = collatz_next(n)
42+
steps += 1
43+
44+
if n > MAX_VALUE:
45+
print("\n\n⚠ Computation stopped: safety limit reached")
46+
break
47+
48+
yield n
49+
path.append(n)
50+
51+
if n in steps_cache:
52+
for remaining in get_remaining_sequence(n):
53+
yield remaining
54+
steps += steps_cache[n]
55+
break
56+
57+
total = steps_cache.get(n, 0)
58+
for value in reversed(path):
59+
total += 1
60+
steps_cache[value] = total
61+
1162
while True:
1263
try:
1364
number = int(input("\nEnter a positive integer to start: "))
1465
if number > 0:
66+
if number > MAX_INPUT:
67+
print(f"Input too large! Maximum allowed: {MAX_INPUT:,}")
68+
continue
1569
break
1670
else:
1771
print("Please enter a positive integer!")
1872
except ValueError:
1973
print("Please enter a valid number!")
2074

2175
original_number = number
22-
sequence = [number]
23-
steps = 0
2476

2577
print(f"\nStarting with: {number}")
2678
print("\nSequence:")
27-
print(number, end="")
28-
29-
while number != 1:
30-
if number % 2 == 0:
31-
number = number // 2
32-
else:
33-
number = 3 * number + 1
34-
35-
sequence.append(number)
79+
80+
sequence = []
81+
steps = 0
82+
max_value = number
83+
84+
gen = collatz_sequence(number)
85+
86+
first = next(gen)
87+
print(first, end="")
88+
sequence.append(first)
89+
90+
for num in gen:
91+
sequence.append(num)
3692
steps += 1
37-
38-
print(f" → {number}", end="")
39-
93+
max_value = max(max_value, num)
94+
print(f" → {num}", end="")
4095
if steps % 10 == 0:
4196
print()
4297

@@ -46,7 +101,7 @@
46101
print(f"Starting number: {original_number}")
47102
print(f"Total steps: {steps}")
48103
print(f"Sequence length: {len(sequence)}")
49-
print(f"Highest number reached: {max(sequence)}")
104+
print(f"Highest number reached: {max_value}")
50105

51106
if len(sequence) <= 100:
52107
view_details = input("\nWould you like to see step-by-step details? (yes/no): ").lower()

0 commit comments

Comments
 (0)