Overview
The following code is a solution for a Project Euler+ problem on Hackerrank. A circular prime is a prime number whose rotations are also prime. For example, 197 is a circular prime since it and all it's rotations (197, 971, 719) are prime.
The sum of all circular primes less than 100 is:
sum(2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, 97) = 446
Code Redability
After learning about list comprehensions in python, I'm concerned that my code readability may have taken a nosedive. I'd like to make my code as understandable as possible so that someone reading it could quickly deduce the strategy I used to solve the problem.
I'm mostly concerned with my generate_circular_primes_less_than
function as it goes 5 nested blocks deep and seems to be more confusing than it could be.
Here's the code for my solution:
from math import sqrt, ceil
from functools import reduce
# generates a list of n booleans where indexes correspond to primality
def prime_sieve(n):
N = [True] * n
N[0] = False
N[1] = False
for i in range(2, int(ceil(sqrt(n)))):
if N[i]:
for j in range(i*2, n, i):
N[j] = False
return N
# rotates the first i chars of a string to the end
def rotate(s, i):
return s[i:] + s[:i]
def generate_circular_primes_less_than(n):
large = 10**len(str(n))
is_prime = prime_sieve(large)
for num in range(n):
if is_prime[num]:
s = str(num)
rotations = [int(rotate(s, i)) for i in range(len(s))]
if reduce(lambda y, x: y and is_prime[x], rotations, True):
for circular_prime in (r for r in rotations if r < n and is_prime[r]):
is_prime[circular_prime] = False # remove duplicates (like 11)
yield circular_prime
else:
for r in rotations:
is_prime[r] = False # no need to recheck non-circular primes
#
# MAIN
if __name__ == "__main__":
n = int(input())
print(sum(generate_all_circular_primes_less_than(n)))
However, the pseudocode I wrote when designing my solution is much simpler:
1. sieve all primes less than the maximum rotation value 2. get the rotations for each prime less than n if all rotations are prime: add the rotations less than n to the sum
Sometimes it seams that adding comments only masks unintuitive code (like putting lipstick on a pig). What would you suggest to improve the readability?
ceil
returns an Integer so you can replaceint(ceil(sqrt(n)))
withceil(sqrt(n))
if your program does not need to be backwards-compatible \$\endgroup\$