|
| 1 | +""" |
| 2 | +The number 197 is called a circular prime because all rotations of the digits: |
| 3 | +197, 971, and 719, are themselves prime. |
| 4 | +There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, |
| 5 | +79, and 97. |
| 6 | +How many circular primes are there below one million? |
| 7 | +
|
| 8 | +To solve this problem in an efficient manner, we will first mark all the primes |
| 9 | +below 1 million using the Seive of Eratosthenes. Then, out of all these primes, |
| 10 | +we will rule out the numbers which contain an even digit. After this we will |
| 11 | +generate each circular combination of the number and check if all are prime. |
| 12 | +""" |
| 13 | +from typing import List |
| 14 | + |
| 15 | +seive = [True] * 1000001 |
| 16 | +i = 2 |
| 17 | +while i * i <= 1000000: |
| 18 | + if seive[i]: |
| 19 | + for j in range(i * i, 1000001, i): |
| 20 | + seive[j] = False |
| 21 | + i += 1 |
| 22 | + |
| 23 | + |
| 24 | +def is_prime(n: int) -> bool: |
| 25 | + """ |
| 26 | + For 2 <= n <= 1000000, return True if n is prime. |
| 27 | + >>> is_prime(87) |
| 28 | + False |
| 29 | + >>> is_prime(23) |
| 30 | + True |
| 31 | + >>> is_prime(25363) |
| 32 | + False |
| 33 | + """ |
| 34 | + return seive[n] |
| 35 | + |
| 36 | + |
| 37 | +def contains_an_even_digit(n: int) -> bool: |
| 38 | + """ |
| 39 | + Return True if n contains an even digit. |
| 40 | + >>> contains_an_even_digit(0) |
| 41 | + True |
| 42 | + >>> contains_an_even_digit(975317933) |
| 43 | + False |
| 44 | + >>> contains_an_even_digit(-245679) |
| 45 | + True |
| 46 | + """ |
| 47 | + return any(digit in "02468" for digit in str(n)) |
| 48 | + |
| 49 | + |
| 50 | +def find_circular_primes(limit: int = 1000000) -> List[int]: |
| 51 | + """ |
| 52 | + Return circular primes below limit. |
| 53 | + >>> len(find_circular_primes(100)) |
| 54 | + 13 |
| 55 | + >>> len(find_circular_primes(1000000)) |
| 56 | + 55 |
| 57 | + """ |
| 58 | + result = [2] # result already includes the number 2. |
| 59 | + for num in range(3, limit + 1, 2): |
| 60 | + if is_prime(num) and not contains_an_even_digit(num): |
| 61 | + str_num = str(num) |
| 62 | + list_nums = [int(str_num[j:] + str_num[:j]) for j in range(len(str_num))] |
| 63 | + if all(is_prime(i) for i in list_nums): |
| 64 | + result.append(num) |
| 65 | + return result |
| 66 | + |
| 67 | + |
| 68 | +if __name__ == "__main__": |
| 69 | + print(f"{len(find_circular_primes()) = }") |
0 commit comments