-
Notifications
You must be signed in to change notification settings - Fork 0
/
collatz.py
133 lines (111 loc) · 3.97 KB
/
collatz.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""Functions dealing with the Collatz conjecture."""
class Bcolors:
"""Perty colors."""
PURPLE = '\033[95m'
BLUE = '\033[94m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def validate_num(n):
"""Attempt to typecast n as an integer."""
try:
n = int(n)
except:
print('Error validating number. Please only use positive integers.')
return 0
else:
return n
def test_num(n):
"""Test if an integer, n reduces to 1 applying the rules.
if n is even, divide it by two, and if n is odd, 3n+1.
"""
n = validate_num(n)
if n:
steps = 0
new_value = n
print(str(n) + ' ', end='')
while new_value != 1:
if steps > 100000:
print('Congratulations! You may have disproved the conjecture!')
print(n)
break
old_value = new_value
steps += 1
if new_value % 2 == 0:
new_value = new_value / 2
if new_value < old_value:
print(Bcolors.RED + str(new_value) + ' ' + Bcolors.ENDC, end='')
else:
print(Bcolors.GREEN + str(new_value) + ' ' + Bcolors.ENDC, end='')
else:
new_value = new_value * 3 + 1
if new_value < old_value:
print(Bcolors.RED + str(new_value) + ' ' + Bcolors.ENDC, end='')
else:
print(Bcolors.GREEN + str(new_value) + ' ' + Bcolors.ENDC, end='')
if new_value == 1:
print('')
print(str(n) + ' converged to 1 in ' + str(steps) + ' steps')
else:
print("Exiting function.")
def test_range(init, final):
"""Test a range of numbers, using range with initial and final values."""
init = validate_num(init)
final = validate_num(final)
if init and final and final > init:
final += 1
for i in range(init, final):
steps = 0
new_value = i
while new_value != 1:
if steps > 10000:
print('10000 steps exceeded! Investigate ' + str(i) +
' furthur!')
break
steps += 1
if new_value % 2 == 0:
new_value = new_value / 2
else:
new_value = new_value * 3 + 1
print(str(i) + ' converged to 1 in ' + str(steps) + ' steps')
else:
print('Exiting function.')
print('Example usage: test_range(1,1000)')
def test_range_dict(init, final):
"""Test a range of numbers, using range with initial and final values.
Uses dict lookup to optimize calculation time.
"""
init = validate_num(init)
final = validate_num(final)
if init and final and final > init:
final += 1
dict_nums = {}
for i in range(init, final):
steps = 0
new_value = i
while new_value != 1:
if steps > 10000:
print('10000 steps exceeded! Investigate ' + str(new_value) +
' furthur!')
break
if new_value in dict_nums:
dict_nums[i] = steps + dict_nums[new_value]
print(Bcolors.GREEN + str(i) + ' reached 1 in ' +
str(dict_nums[i]) + ' steps' + Bcolors.ENDC)
break
else:
steps += 1
if new_value % 2 == 0:
new_value = new_value / 2
else:
new_value = new_value * 3 + 1
else:
dict_nums[i] = steps
print(str(i) + ' converged to 1 in ' + str(dict_nums[i]) +
' steps')
else:
print('Exiting function.')
print('Example usage: test_range_dict(1,1000)')