Last active
September 28, 2019 06:02
-
-
Save gordol/3e44a3375005b99e97b659b0012d18fa to your computer and use it in GitHub Desktop.
A simple little module to complete the prime number challenge. Includes 4 tests. This could be made to be much much faster if we used PyPy and NumPy, but the challenge was to utilize the standard library only. To run the tests, run: `python -m unittest prime-challenge`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import itertools | |
import unittest | |
def primeGenerator(): | |
""" | |
Yields an array of primes. | |
""" | |
primes = [2] | |
sequence = 0 | |
yield primes | |
for candidate in itertools.count(3, 2): | |
prime = True | |
for sequence in primes: | |
# mod check | |
if candidate % sequence == 0: | |
prime = False | |
break | |
# exp check | |
if sequence ** 2 > candidate: | |
break | |
if prime: | |
primes.append(candidate) | |
yield primes | |
def primeMatrix(num_primes): | |
""" | |
Generates a two dimensional array of prime products. | |
""" | |
gen = primeGenerator() | |
for _ in range(1, num_primes): | |
next(gen) | |
primes = next(gen) | |
prime_grid = [[0] + primes] | |
for x_idx, x_value in enumerate(primes): | |
prime_grid.append([x_value]) | |
for y_idx, y_value in enumerate(primes): | |
prime_grid[-1].append(x_value * y_value) | |
return prime_grid | |
def formatMatrix(matrix): | |
""" | |
Returns a nicely formatted string of the two dimensional matrix | |
""" | |
return '\n'.join([ | |
''.join(['{:4}'.format(item) for item in row]) for row in matrix | |
]) | |
class TestPrimeTools(unittest.TestCase): | |
def setUp(self): | |
self.matrix = primeMatrix(10) | |
self.first_10_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] | |
def testPrimeGenerator(self): | |
gen = primeGenerator() | |
primes = [] | |
for _ in range(0, 10): | |
primes = next(gen) | |
self.assertEqual( | |
primes, | |
self.first_10_primes, | |
'The first 10 primes are incorrect.' | |
) | |
def testFirstRow(self): | |
self.assertEqual( | |
self.matrix[0][1:], | |
self.first_10_primes, | |
'The first row is incorrect.' | |
) | |
def testFirstColumn(self): | |
self.assertEqual( | |
[row[0] for row in self.matrix[1:]], | |
self.first_10_primes, | |
'The first column is incorrect.' | |
) | |
def testMatrix(self): | |
expected_matrix = [ | |
[0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29], | |
[2, 4, 6, 10, 14, 22, 26, 34, 38, 46, 58], | |
[3, 6, 9, 15, 21, 33, 39, 51, 57, 69, 87], | |
[5, 10, 15, 25, 35, 55, 65, 85, 95, 115, 145], | |
[7, 14, 21, 35, 49, 77, 91, 119, 133, 161, 203], | |
[11, 22, 33, 55, 77, 121, 143, 187, 209, 253, 319], | |
[13, 26, 39, 65, 91, 143, 169, 221, 247, 299, 377], | |
[17, 34, 51, 85, 119, 187, 221, 289, 323, 391, 493], | |
[19, 38, 57, 95, 133, 209, 247, 323, 361, 437, 551], | |
[23, 46, 69, 115, 161, 253, 299, 391, 437, 529, 667], | |
[29, 58, 87, 145, 203, 319, 377, 493, 551, 667, 841]] | |
self.assertEqual( | |
self.matrix, | |
expected_matrix, | |
'The matrix format is incorrect.' | |
) | |
if __name__ == "__main__": | |
print(formatMatrix(primeMatrix(10))) |
Here's the execution profile under PyPy. Notice the MUCH faster execution time, and slightly less memory usage than the standard variant above, but still more memory usage than the NumPy variant, and it's slower.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is an execution profile from generating the matrix with 10,000 primes.