Skip to content

Instantly share code, notes, and snippets.

@gordol
Last active September 28, 2019 06:02
Show Gist options
  • Save gordol/3e44a3375005b99e97b659b0012d18fa to your computer and use it in GitHub Desktop.
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`
#!/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)))
@gordol
Copy link
Author

gordol commented Sep 27, 2019

Here is an execution profile from generating the matrix with 10,000 primes.

execution profile

@gordol
Copy link
Author

gordol commented Sep 27, 2019

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.

pypy execution profile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment