python - Speeding up string splitting and concatenation -
i'm trying solve project euler's problem #35
the number, 197, called circular prime because rotations of digits: 197, 971, , 719, prime.
how many circular primes there below 1 million?
this solution:
import numpy np def problem(n=100): circulars = np.array([], np.int32) p = np.array(sieveofatkin(n), np.int32) prime in p: prime_str = str(prime) is_circular = true in xrange(len(prime_str)): m = int(prime_str[i:]+prime_str[:i]) if not m in p: is_circular = false if is_circular: circulars = np.append(circulars, [prime]) return len(circulars)
unfortunately for-loop mighty slow! ideas how can speed up? suspect string concatenation bottleneck, not entirely sure! :)
any ideas? :)
use set membership testing instead of array. hash lookup o(1) instead of o(n). biggest bottleneck.
break out of loop see it's not circular prime instead of trying other rotations. bottleneck.
here, i've isolated circularity testing function allow list built list comprehension. having in function, lets return false
know it's not circular. alternative in for
loop , break
when know it's not circular. append list in loop's else
clause. speaking, list comps faster appending in loop though. might not case here because add function call overhead. if care speed, worth profile both options.
primes = set(primes_to_one_million_however_you_want_to_get_them) def is_circular(prime, primes=primes): prime_str = str(prime) # sven marnach's comments return all(int(prime_str[i:]+prime_str[:i]) in primes in xrange(len(prime_str))) circular_primes = [p p in primes if is_circular(p)]
i've used trick of passing global default argument is_circular
function. means can accessed within function local variable instead of global variable faster.
here's 1 way code using else
clause on loop rid of ugly flag , improve efficiency.
circular = [] p in primes: prime_str = str(prime) in xrange(len(prime_str)): if int(prime_str[i:]+prime_str[:i]) not in primes: break else: circular.append(p)
Comments
Post a Comment