-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprime.py
executable file
·338 lines (248 loc) · 9.2 KB
/
prime.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
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
#!/usr/bin/env python
## \file Prime.py
##
## \author David Weber
##
## \brief This file will calculate all of the prime numbers from
## 1-N. Depending on the command line arguments, it will
## use one of several algorithms
##
## \Note Comments are in the doxygen style. Any recent
## version of doxygen should be able to create appropriate
## external documentation for this file
from optparse import OptionParser
import sys
from math import sqrt
## \brief This class provides several algorithms to calculate
## prime numbers
class Prime:
## \param self Pointer to object instance
## \param N The upper bound used to locate prime numbers
## \returns True if N is valid, False otherwise
def _validate(self, N):
# Make sure that N is not "None" or
# Negative or
# equal to 0 or
# equal to 1
if None == N or \
N != abs(N) or \
0 == N or \
1 == N:
return False
return True
#end _validate
## \brief Method used to find the primes in a brute force
## and very slow method
##
## \param self Pointer to object instance
##
## \param N The upper bound used to locate prime numbers
## method.
##
## \exception Exception An "Exception" will be raised if N
## contains invalid data
##
## \returns List of the found prime numbers
def bruteForce(self, N):
# Validate the input
if not self._validate(N):
raise Exception("%s is an invalid upper bound." % N)
# Declare the return value
retValue = []
# Loop through our possible values
for i in xrange(2, N+1):
notPrime = False
# Calculate the square root, because this will be the upper
# bounds of our inner loop
squareRoot = sqrt(i)
j = 2
while (j <= squareRoot):
# If evenly divisible, it's not prime, so exit the inner loop
if i % j == 0:
notPrime = True
break
j += 1 # Increment the inner loop
# end while
# Add it to the list if it is prime
if not notPrime:
retValue.append(i)
i += 1 # Increment the outer loop
# end while
# Return the list
return retValue
#end bruteForce
## \brief Method used to find the primes in a "better" brute force method
##
## \param self Pointer to object instance
##
## \param N The upper bound used to locate prime numbers
## method.
##
## \note This is better than the bruteForce() above, because we only check
## to see if we are divisible by any found primes inside the inner
## loop
##
## \exception Exception An "Exception" will be raised if N
## contains invalid data
##
## \returns List of the found prime numbers
def betterBruteForce(self, N):
# Validate the input
if not self._validate(N):
raise Exception("%s is an invalid upper bound." % N)
# Declare the return value
retValue = []
# Loop through our possible values
for i in xrange(2, N+1):
notPrime = False
# Calculate the square root, because this will be the upper
# bounds of our inner loop
squareRoot = sqrt(i)
# Loop through all of the found primes only
for j in retValue:
# No need to check primes larger than the square root of i
if j > squareRoot:
break
# If evenly divisible, it's not prime, so bail out of
# the inner loop
if i % j == 0:
notPrime = True
break
# end for
# Add it to the list if it is prime
if not notPrime:
retValue.append(i)
i += 1 # Increment the outer loop
# end while
# Return the list
return retValue
# end betterBruteForce
def sieve_of_eratosthenes(self, N):
# Validate the input
if not self._validate(N):
raise Exception("%s is an invalid upper bound." % N)
# Declare the return value
retValue = []
max_value = int(sqrt(N))
# Declare our data table
data = [True] * (N+1)
data[0] = False
data[1] = False
# Loop through data
index = 2
while index <= max_value:
# Mark the intervals of index as not prime
for i in xrange(index+index, N+1, index):
# print "Marking %i" % i
data[i] = False
# Find the next possible prime
index += 1
while index < max_value and not data[index]:
index += 1
# print "Next possible prime: %i" % index
# Create our output
for i in xrange(0, N+1):
if data[i]:
retValue.append(i)
# Return the list
return retValue
# end sieve_of_eratosthenes
## \brief Method used to parse the command line arguments, and ensure
## that the required elements have been filled out
##
## \returns "options" object returned from a call to the Python
## OptionParser object instance parse_args() call
def parseArgs():
# Declare the option parser
optParse = OptionParser()
# Add options for the various algorithms
optParse.add_option("-n", dest="N", action="store",
help="The upper limit of the primes you wish to find")
# Add options for the various algorithms
optParse.add_option("-b", dest="bruteForce", action="store_true",
help="Calculate primes using the brute force algorithm")
optParse.add_option("-B", dest="betterBF", action="store_true",
help="Calculate primes using a better brute force algorithm")
optParse.add_option("-s", dest="sieve", action="store_true",
help="Calculate primes using the Sieve of Eratosthenes")
# If the user requested help, simply exit the application
if "-h" in sys.argv:
optParse.print_help()
exit(0)
# Verify that at least one algorithm has been specified
algArgList = ["-b", "-B", "-s"]
hasAlg = False
# Look for one algorithm argument in the command line arguments
for alg in algArgList:
if alg in sys.argv:
hasAlg = True
# If no algorithms have been specified, exit
if not hasAlg:
print("*** No algorithm arguments specified ***")
optParse.print_help()
sys.exit(-1)
# Ensure that N has been passed in from the command line
elif "-n" not in sys.argv:
print("*** Upper bound not specified ***")
optParse.print_help()
sys.exit(-1)
# Parse the options
(options, args) = optParse.parse_args()
# Did they specify "-n" with nothing following it?
# Does N have non-number items in it?
# Is N passed in as a floating point number?
if None == options.N or \
not options.N.isdigit() or \
"." in options.N:
print("*** -n must be followed by a positive integer ***")
optParse.print_help()
sys.exit(-1)
return options
#end parseArgs
## \brief "Main" function where the execution starts when called
## as a stand-alone script
def Main():
# Parse the command line arguments
options = parseArgs()
# Instantiate a prime class
primeInstance = Prime()
# Cast options.N to an integer (since we parse it as a string)
N = int(options.N)
# Calculate primes using the brute force method
if options.bruteForce:
# Try to calculate the primes in the given range
try:
primes = primeInstance.bruteForce(N)
# Print out the exception
except Exception, e:
print e
exit(-1)
# Print out the primes
print("The primes between 1 and %s using the brute force method are:" % options.N)
for num in primes:
print num
# Calculate the primes using the "better" brute force method
elif options.betterBF:
# Try to calculate the primes in the given range
try:
primes = primeInstance.betterBruteForce(N)
# Print out the exception
except Exception, e:
print e
exit(-1)
# Print out the primes
print("The primes between 1 and %s using the \"better\" brute force method are:" % options.N)
for num in primes:
print num
elif options.sieve:
# Try to calculate the primes in the given range
primes = primeInstance.sieve_of_eratosthenes(N)
# Print out the primes
print("The primes between 1 and %s using the Sieve of Eratosthenes method are:" % options.N)
for num in primes:
print num
#end Main
# This condition is true only if called as a stand alone script
# We call our main function to perform the majority of the work
if __name__ == "__main__":
Main()