primes.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. UPPER_BOUND = 5000000
  2. PREFIX = 32338
  3. class Node:
  4. def __init__(self):
  5. self.children = {}
  6. self.terminal = False
  7. class Sieve:
  8. def __init__(self, limit):
  9. self.limit = limit
  10. self.prime = [False] * (limit + 1)
  11. def to_list(self):
  12. result = [2, 3]
  13. for p in range(5, self.limit + 1):
  14. if self.prime[p]:
  15. result.append(p)
  16. return result
  17. def omit_squares(self):
  18. r = 5
  19. while r * r < self.limit:
  20. if self.prime[r]:
  21. i = r * r
  22. while i < self.limit:
  23. self.prime[i] = False
  24. i = i + r * r
  25. r = r + 1
  26. return self
  27. def step1(self, x, y):
  28. n = (4 * x * x) + (y * y)
  29. if n <= self.limit and (n % 12 == 1 or n % 12 == 5):
  30. self.prime[n] = not self.prime[n]
  31. def step2(self, x, y):
  32. n = (3 * x * x) + (y * y)
  33. if n <= self.limit and n % 12 == 7:
  34. self.prime[n] = not self.prime[n]
  35. def step3(self, x, y):
  36. n = (3 * x * x) - (y * y)
  37. if x > y and n <= self.limit and n % 12 == 11:
  38. self.prime[n] = not self.prime[n]
  39. def loop_y(self, x):
  40. y = 1
  41. while y * y < self.limit:
  42. self.step1(x, y)
  43. self.step2(x, y)
  44. self.step3(x, y)
  45. y = y + 1
  46. def loop_x(self):
  47. x = 1
  48. while x * x < self.limit:
  49. self.loop_y(x)
  50. x = x + 1
  51. def calc(self):
  52. self.loop_x()
  53. return self.omit_squares()
  54. def generate_trie(l):
  55. root = Node()
  56. for el in l:
  57. head = root
  58. for ch in str(el):
  59. if ch not in head.children:
  60. head.children[ch] = Node()
  61. head = head.children[ch]
  62. head.terminal = True
  63. return root
  64. def find(upper_bound, prefix):
  65. primes = Sieve(upper_bound).calc()
  66. str_prefix = str(prefix)
  67. head = generate_trie(primes.to_list())
  68. for ch in str_prefix:
  69. if ch not in head.children:
  70. return None
  71. head = head.children[ch]
  72. if head is None:
  73. return None
  74. queue, result = [(head, str_prefix)], []
  75. while queue:
  76. top, prefix = queue.pop()
  77. if top.terminal:
  78. result.append(int(prefix))
  79. for ch, v in top.children.items():
  80. queue.insert(0, (v, prefix + ch))
  81. result.sort()
  82. return result
  83. def verify():
  84. left = [2, 23, 29]
  85. right = find(100, 2)
  86. if left != right:
  87. print(f"{left} != {right}")
  88. exit(1)
  89. verify()
  90. results = find(UPPER_BOUND, PREFIX)
  91. assert results == [323381, 323383, 3233803, 3233809, 3233851, 3233863, 3233873, 3233887, 3233897]