-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFunctions.py
More file actions
211 lines (167 loc) · 5.26 KB
/
Functions.py
File metadata and controls
211 lines (167 loc) · 5.26 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
from collections import Counter
from functools import lru_cache, reduce
@lru_cache(None)
def IsPrime(n):
if n < 2:
return False
elif n < 4:
return True
else:
if not n % 2:
return False
for f in range(3, 1 + int(n ** .5), 2):
if not n % f:
return False
return True
@lru_cache(None)
def PrimeFactors(n, self=True, unique=False):
factors = []
if n >= 2:
p = 2
while n % p == 0:
factors.append(p)
n //= p
for p in range(3, 1 + int(n ** .5), 2):
while n % p == 0:
factors.append(p)
n //= p
if n == 1:
break
if n > 1 and self: factors.append(n)
if unique:
factors = set(factors)
else:
factors = Counter(factors)
return factors
@lru_cache(None)
def PrimeFactors2(n, self=True, unique=False):
factors = dict()
if n < 2:
return factors
for p in PrimeSieve(1 + int(n ** .5)):
while n % p == 0:
factors.setdefault(p, 0)
factors[p] += 1
n //= p
if unique:
factors[p] = 1
if n == 1:
break
if n > 1 and self: factors[n] = 1
return factors
@lru_cache(None)
def Factors(x):
from math import sqrt, ceil
facs = []
for n in range(1, ceil(sqrt(x))):
if x % n == 0:
facs.append(n)
for fac in facs[1:][::-1]:
facs.append(x // fac)
if abs(sqrt(x) - round(sqrt(x))) < 1e-6:
facs.append(round(sqrt(x)))
return facs
@lru_cache(None)
def IsPanDig(x, end=9, begin=1):
temp = list(str(x))
temp.sort()
return temp == [str(y) for y in range(begin, end + 1)]
def GCD(x, y=None):
numbers = set()
for i in [x, y]:
if hasattr(x, "__iter__"):
numbers.update(i)
else:
numbers.update([i])
numbers = set(filter(bool, numbers))
def GCDpair(x, y):
if x == 0:
return y
else:
return GCDpair(y % x, x)
return reduce(GCDpair, numbers)
def LCM(x, y=None):
numbers = set()
for i in [x, y]:
if hasattr(x, "__iter__"):
numbers.update(i)
else:
numbers.update([i])
numbers = set(filter(bool, numbers))
def LCMpair(x, y):
return x // GCD(x, y) * y
return reduce(LCMpair, x)
def PrimeSieve(valLimit=float('inf'), lengthLimit=float('inf')):
def FastPrimeSieve(valLimit, lengthLimit=float('inf')):
valLimit = int(valLimit)
primeList = [False, False, True] + [True, False] * ((valLimit - 2) // 2)
# note that we have currently found no primes
currentLength = 0
for number, numberIsPrime in enumerate(primeList):
if currentLength == lengthLimit:
break
if numberIsPrime:
for k in range(number * number, valLimit, number):
primeList[k] = False
yield number
currentLength += 1
def InfPrimeSieve(lengthLimit=float('inf')):
"""
algorithm is Sieve of Eratosthenes with optimization of starting at
square of primes.
"""
# dictionary holding lists of the primes that are a factor of the composite
composites = {}
# set the number that we are testing for primality
number = 2
# note that we have currently found no primes
currentLength = 0
while number < valLimit and currentLength < lengthLimit:
if number not in composites:
'''
since number is not a composite it is a new prime. mark the
square of the prime, since the square is the first multiple of
the prime that is not a multiple of another prime
'''
yield number
composites[number ** 2] = [number]
else:
'''number is composite. composites[number] is the list of primes
that divide it. mark the *next* multiple of each prime as having
that prime as a factor'''
for p in composites[number]:
composites.setdefault(p + number, []).append(p)
del composites[number]
number += 1
'''
some problems require a fixed list of primes and some require that we
can extend the list at will. The fixed list is much faster to generate
and then be done with, so use that whenever possible
'''
if valLimit==float('inf'):
temp = InfPrimeSieve(lengthLimit)
else:
temp = FastPrimeSieve(valLimit, lengthLimit)
return(temp)
if __name__ == '__main__':
from time import clock
limit = 10000
start = clock()
y = [PrimeFactors(x) for x in range(limit)]
# print(y)
print(clock() - start)
start = clock()
z = [PrimeFactors2(x) for x in range(limit)]
# print(z)
print(clock() - start)
print(y == z)
limit = 100000000
start = clock()
y = [PrimeFactors(x) for x in range(limit-1000, limit)]
# print(y)
print(clock() - start)
start = clock()
z = [PrimeFactors2(x) for x in range(limit-1000, limit)]
# print(z)
print(clock() - start)
print(y == z)