-
Notifications
You must be signed in to change notification settings - Fork 0
/
totient.py
110 lines (95 loc) · 2.55 KB
/
totient.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
class Prime(dict):
def __init__(self):
dict.__init__(self)
self[1] = False
self[2] = True
def primelist(self):
x = 2
while True:
if self[x]:
yield x
x+=1
def __getitem__(self, key):
if key in self:
return dict.__getitem__(self, key)
else:
if isPrime(key):
self[key] = True
else:
self[key] = False
return dict.__getitem__(self, key)
def isPrime(n):
if (n<2):
return False
if (n%2==0):
return False
for i in range(3,n/2,2):
if (n%i==0):
return False
return True
primes = Prime()
def pfactorsbrute(n):
current = n
primefactors = dict()
prime = 2
for prime in primes.primelist():
if primes[current]:
break
else:
while not primes[current] and (current%prime) == 0:
current = current/prime
if prime in primefactors:
primefactors[prime]+=1
else:
primefactors[prime]=1
if current in primefactors:
primefactors[current] += 1
else:
# print "Setting primefactors @ %d to 1" % current
primefactors[current] = 1
return primefactors
def gcd(a, b):
"Euclid's Algorithm"
while b:
a, b = b, a%b
return a
def totient(n):
print "Totient of ", n
"""
Compute the number of positives < n that are
relatively prime to n -- good solution!
"""
# Case 1. n == 1
if n == 1:
print "Case 1"
return 0
factors = pfactorsbrute(n)
#Case 2. n is prime
if len(factors) == 0:
print "Case 2"
return n-1
#Case 3. n has two relatively prime factors
if len(factors) == 2:
mn = []
for factor in factors:
exp = factors[factor]
mn.append(factor**exp)
if gcd(mn[0], mn[1]) == 1:
print "Case 3. %d and %d are coprime" % (mn[0], mn[1])
return totient(mn[0])*totient(mn[1])
print "Cases 4 and 5"
components = []
for factor in factors:
exp = factors[factor]
components.append(factor**exp - factor**(exp-1))
print "Prime factors: %s" % (factors)
tot = reduce(lambda x, y: x*y, components)
return tot
if __name__ == "__main__":
print totient(240)
print
print totient(13)
print
print totient(10)
print
print totient(49)