|
| 1 | +""" |
| 2 | +The number 3797 has an interesting property. Being prime itself, it is possible |
| 3 | +to continuously remove digits from left to right, and remain prime at each stage: |
| 4 | +3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3. |
| 5 | +
|
| 6 | +Find the sum of the only eleven primes that are both truncatable from left to right |
| 7 | +and right to left. |
| 8 | +
|
| 9 | +NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes. |
| 10 | +""" |
| 11 | + |
| 12 | + |
| 13 | +from typing import List |
| 14 | + |
| 15 | +seive = [True] * 1000001 |
| 16 | +seive[1] = False |
| 17 | +i = 2 |
| 18 | +while i * i <= 1000000: |
| 19 | + if seive[i]: |
| 20 | + for j in range(i * i, 1000001, i): |
| 21 | + seive[j] = False |
| 22 | + i += 1 |
| 23 | + |
| 24 | + |
| 25 | +def is_prime(n: int) -> bool: |
| 26 | + """ |
| 27 | + Returns True if n is prime, |
| 28 | + False otherwise, for 1 <= n <= 1000000 |
| 29 | + >>> is_prime(87) |
| 30 | + False |
| 31 | + >>> is_prime(1) |
| 32 | + False |
| 33 | + >>> is_prime(25363) |
| 34 | + False |
| 35 | + """ |
| 36 | + return seive[n] |
| 37 | + |
| 38 | + |
| 39 | +def list_truncated_nums(n: int) -> List[int]: |
| 40 | + """ |
| 41 | + Returns a list of all left and right truncated numbers of n |
| 42 | + >>> list_truncated_nums(927628) |
| 43 | + [927628, 27628, 92762, 7628, 9276, 628, 927, 28, 92, 8, 9] |
| 44 | + >>> list_truncated_nums(467) |
| 45 | + [467, 67, 46, 7, 4] |
| 46 | + >>> list_truncated_nums(58) |
| 47 | + [58, 8, 5] |
| 48 | + """ |
| 49 | + str_num = str(n) |
| 50 | + list_nums = [n] |
| 51 | + for i in range(1, len(str_num)): |
| 52 | + list_nums.append(int(str_num[i:])) |
| 53 | + list_nums.append(int(str_num[:-i])) |
| 54 | + return list_nums |
| 55 | + |
| 56 | + |
| 57 | +def validate(n: int) -> bool: |
| 58 | + """ |
| 59 | + To optimize the approach, we will rule out the numbers above 1000, |
| 60 | + whose first or last three digits are not prime |
| 61 | + >>> validate(74679) |
| 62 | + False |
| 63 | + >>> validate(235693) |
| 64 | + False |
| 65 | + >>> validate(3797) |
| 66 | + True |
| 67 | + """ |
| 68 | + if len(str(n)) > 3: |
| 69 | + if not is_prime(int(str(n)[-3:])) or not is_prime(int(str(n)[:3])): |
| 70 | + return False |
| 71 | + return True |
| 72 | + |
| 73 | + |
| 74 | +def compute_truncated_primes(count: int = 11) -> List[int]: |
| 75 | + """ |
| 76 | + Returns the list of truncated primes |
| 77 | + >>> compute_truncated_primes(11) |
| 78 | + [23, 37, 53, 73, 313, 317, 373, 797, 3137, 3797, 739397] |
| 79 | + """ |
| 80 | + list_truncated_primes = [] |
| 81 | + num = 13 |
| 82 | + while len(list_truncated_primes) != count: |
| 83 | + if validate(num): |
| 84 | + list_nums = list_truncated_nums(num) |
| 85 | + if all(is_prime(i) for i in list_nums): |
| 86 | + list_truncated_primes.append(num) |
| 87 | + num += 2 |
| 88 | + return list_truncated_primes |
| 89 | + |
| 90 | + |
| 91 | +if __name__ == "__main__": |
| 92 | + print(f"{sum(compute_truncated_primes(11)) = }") |
0 commit comments