1
0

primes.py 2.7 KB

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