Петко обнови решението на 01.05.2012 13:34 (преди над 12 години)
+"""
+Created on May 1, 2012
+
+@author: ppadevski
+"""
+from bisect import bisect_left
+from itertools import takewhile
+from math import sqrt
+
+_memory = [2]
+
+def _ensure_primes(lower_limit):
+ """
+ Ensures that there is a prime number ready to be picked by any generator.
+
+ @type lower_limit: C{int}
+ @param lower_limit: The lower limit of prime numbers to pre-generate.
+
+ @note: Modifies the cached _memory with primes.
+ """
+ iterations = 1
+ while _memory[-1] < lower_limit:
+ n = _memory[-1] + iterations
+ success = True
+
+ upper_limit = sqrt(n)
+ for prime_number in takewhile(lambda x: x <= upper_limit, _memory):
+ if n % prime_number == 0:
+ success = False
+ break
+
+ if success:
+ _memory.append(n)
+ iterations += 1
+
+ return _memory
+
+def _is_prime(number):
+ """
+ Checks if the passed number is in fact a prime.
+ @pre: All primes lower or equal to the number are already found.
+
+ @type number: C{int}
+ @param number: The number to check.
+
+ @rtype: C{bool}
+ @return: True iff the number is prime, False otherwise
+ """
+ pos = bisect_left(_memory, number)
+ return pos != len(_memory) and _memory[pos] == number
+
+def primes():
+ """
+ Creates a generator which iterates over prime numbers.
+ """
+ n = 2
+ while True:
+ _ensure_primes(n)
+
+ if _is_prime(n):
+ yield n
+
+ n += 1
+
+def semiprimes():
+ """
+ Creates a generator which iterates over semi-prime numbers
+
+ @note: A semi-prime number is a number that is a result of the
+ multiplication of two prime numbers.
+ """
+ n = 2
+ while True:
+ prime_numbers = _ensure_primes(n / 2)
+
+ upper_limit = sqrt(n)
+ for p in takewhile(lambda x: x <= upper_limit, prime_numbers):
+ if n % p == 0 and _is_prime(n / p):
+ yield n
+ break
+
+ n += 1