patternpythonMinor
Sieve of Atkin in Python
Viewed 0 times
atkinpythonsieve
Problem
I recently implemented the Sieve of Atkin prime generating algorithm in Python. Though I know the term "pythonic" isn't exactly set in stone, I can tell that my program doesn't quite take advantage of python's inherent traits; my program looks like it was written with "C" in mind.
My question is two fold; (1) how can I make this more pythonic, and (2) how can I improve its performance?
I suspect the solution lies in making less use of lists in lieu of generators, but I'm not sure how to do so here:
My question is two fold; (1) how can I make this more pythonic, and (2) how can I improve its performance?
I suspect the solution lies in making less use of lists in lieu of generators, but I'm not sure how to do so here:
def atkin_sieve(limit):
sieve_list = [-1]*limit
sieve_list[2] *= -1
sieve_list[3] *= -1
x = 1
# Part I: preliminary work
while(x*x y:
sieve_list[n] *= -1
y += 1
x += 1
# Part II: Remove the squares of primes (and their multiples)
r = 5
while r*r 0:
i = r*r
while i 0:
results.append(x)
x += 1
return resultsSolution
So I recast your code to make it a bit more pythonic. For reference, all of the code is at the bottom of this post. I played around a bit looking for some performance improvements, but found nothing significant.
Some notes:
Pep8:
First thing to do is get a style/lint checker. I use the pycharm ide which will show you style and compile issues right in the editor. When you get a chance you should also read through pep8 which is the official python style guide.
Native Types:
I changed all of the
Bug at a boundary:
The sieve_list list was one element too short. I discovered this with a quick sanity test of:
Use python iterators:
This:
became:
And this:
became:
Code:
Some notes:
Pep8:
First thing to do is get a style/lint checker. I use the pycharm ide which will show you style and compile issues right in the editor. When you get a chance you should also read through pep8 which is the official python style guide.
Native Types:
I changed all of the
+/-1 to True/FalseBug at a boundary:
The sieve_list list was one element too short. I discovered this with a quick sanity test of:
print atkin_sieve(28)
print atkin_sieve(29)
print atkin_sieve(30)Use python iterators:
This:
i = r*r
while i < limit:
sieve_list[i] = -1
i += r*rbecame:
for n in range(r_squared, len(sieve_list), r_squared):
sieve_list[n] = FalseAnd this:
results = []
x = 0
for p in sieve_list:
if p > 0:
results.append(x)
x += 1
return resultsbecame:
return [x for x, p in enumerate(sieve_list) if p]Code:
def atkin_sieve(limit):
assert limit > 3
sieve_list = [False] * (limit + 1)
sieve_list[2:4] = (True, True)
# Part I: preliminary work
x = x_squared = 1
while x_squared y:
n = 3 * x_squared - y_squared
if n <= limit and n % 12 == 11:
sieve_list[n] = not sieve_list[n]
y += 1
y_squared = y * y
x += 1
x_squared = x * x
# Part II: Remove the squares of primes (and their multiples)
r = 5
r_squared = r * r
while r_squared < limit:
if sieve_list[r]:
for n in range(r_squared, len(sieve_list), r_squared):
sieve_list[n] = False
r += 1
r_squared = r * r
# Part III: Append everything into a list
return [x for x, p in enumerate(sieve_list) if p]Code Snippets
print atkin_sieve(28)
print atkin_sieve(29)
print atkin_sieve(30)i = r*r
while i < limit:
sieve_list[i] = -1
i += r*rfor n in range(r_squared, len(sieve_list), r_squared):
sieve_list[n] = Falseresults = []
x = 0
for p in sieve_list:
if p > 0:
results.append(x)
x += 1
return resultsreturn [x for x, p in enumerate(sieve_list) if p]Context
StackExchange Code Review Q#156839, answer score: 3
Revisions (0)
No revisions yet.