Compare commits
2 Commits
eb7ec037d2
...
fd4ff495d9
| Author | SHA1 | Date | |
|---|---|---|---|
| fd4ff495d9 | |||
| bf3732794a |
46
python/e111.py
Normal file
46
python/e111.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
from lib_prime import is_prime_rabin_miller as is_prime
|
||||||
|
|
||||||
|
|
||||||
|
def get_permutations(number: str, number_permutations: int, start_index = 0):
|
||||||
|
""" Returns number permutated at number_permutations locations. """
|
||||||
|
if number_permutations == 0:
|
||||||
|
yield int(number)
|
||||||
|
else:
|
||||||
|
numbers = list("0123456789")
|
||||||
|
base = list(str(number))
|
||||||
|
for i in range(start_index, len(base)):
|
||||||
|
digit_stored = base[i]
|
||||||
|
for n in numbers:
|
||||||
|
if n == digit_stored:
|
||||||
|
continue
|
||||||
|
base[i] = n
|
||||||
|
if base[0] == "0":
|
||||||
|
continue
|
||||||
|
for p in get_permutations("".join(base), number_permutations - 1, i):
|
||||||
|
yield p
|
||||||
|
base[i] = digit_stored
|
||||||
|
|
||||||
|
|
||||||
|
def euler_111():
|
||||||
|
result = 0
|
||||||
|
n = 10
|
||||||
|
for d in range(10):
|
||||||
|
subresult = 0
|
||||||
|
base = "".join([str(d) for _ in range(n)])
|
||||||
|
for p in get_permutations(base, 1):
|
||||||
|
if is_prime(p):
|
||||||
|
subresult += p
|
||||||
|
if subresult == 0:
|
||||||
|
# d in [0, 2, 8] requires two permutations to yield at least one prime
|
||||||
|
for p in get_permutations(base, 2):
|
||||||
|
if is_prime(p):
|
||||||
|
subresult += p
|
||||||
|
assert subresult > 0, "More than to permutations required to yield prime"
|
||||||
|
result += subresult
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
solution = euler_111()
|
||||||
|
print("e111.py: " + str(solution))
|
||||||
|
assert(solution == 612407567715)
|
||||||
39
python/lib_bitarray.py
Normal file
39
python/lib_bitarray.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
class Bitarray:
|
||||||
|
def __init__(self, num_bits):
|
||||||
|
self.word_size = 32
|
||||||
|
self.word_mask = 2**self.word_size - 1
|
||||||
|
num_words = num_bits // self.word_size
|
||||||
|
if num_bits % self.word_size != 0:
|
||||||
|
num_words += 1
|
||||||
|
self.num_bits = num_bits
|
||||||
|
self.num_words = num_words
|
||||||
|
self.array = [0] * num_words
|
||||||
|
|
||||||
|
def setall(self, target: bool):
|
||||||
|
if target:
|
||||||
|
self.array = [self.word_mask] * self.num_words
|
||||||
|
else:
|
||||||
|
self.array = [0] * self.num_words
|
||||||
|
|
||||||
|
def set(self, bit, target: bool):
|
||||||
|
assert(bit < self.num_bits)
|
||||||
|
word_index = bit // self.word_size
|
||||||
|
bit_index = bit % self.word_size
|
||||||
|
value = self.array[word_index]
|
||||||
|
if target:
|
||||||
|
value = (value | (1 << bit_index))
|
||||||
|
else:
|
||||||
|
value = (value & (~(1 << bit_index)))
|
||||||
|
self.array[word_index] = value
|
||||||
|
|
||||||
|
def get(self, bit) -> bool:
|
||||||
|
assert(bit < self.num_bits)
|
||||||
|
word_index = bit // self.word_size
|
||||||
|
bit_index = bit % self.word_size
|
||||||
|
return bool(self.array[word_index] & (1 << bit_index))
|
||||||
|
|
||||||
|
def __getitem__(self, bit: int) -> bool:
|
||||||
|
return self.get(bit)
|
||||||
|
|
||||||
|
def __setitem__(self, bit: int, value: bool):
|
||||||
|
self.set(bit, value)
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
from lib_bitarray import Bitarray
|
||||||
try:
|
try:
|
||||||
from lib_misc import get_item_counts
|
from lib_misc import get_item_counts
|
||||||
from lib_misc import product
|
from lib_misc import product
|
||||||
@@ -65,6 +66,34 @@ def is_prime(n):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def is_prime_rabin_miller(number):
|
||||||
|
""" Rabin-Miller Primality Test """
|
||||||
|
witnesses = [2, 3, 5, 7, 11, 13, 17, 23, 29, 31, 37, 41, 43, 47, 53]
|
||||||
|
|
||||||
|
if number in witnesses:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if number % 6 not in [1,5]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
r, s = 1, number - 1
|
||||||
|
while s % 2 == 0:
|
||||||
|
s //= 2
|
||||||
|
r += 1
|
||||||
|
|
||||||
|
for witness in witnesses:
|
||||||
|
remainder = pow(witness, s, number)
|
||||||
|
if remainder == 1:
|
||||||
|
continue
|
||||||
|
for _ in range(1, r):
|
||||||
|
if remainder == number - 1:
|
||||||
|
break
|
||||||
|
remainder = pow(remainder, 2, number)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def prime_nth(n):
|
def prime_nth(n):
|
||||||
"""Returns the nth prime number. The first number
|
"""Returns the nth prime number. The first number
|
||||||
is 1 indexed, i.e. n = 1 -> 2, n = 2 -> 3, etc.
|
is 1 indexed, i.e. n = 1 -> 2, n = 2 -> 3, etc.
|
||||||
@@ -97,12 +126,8 @@ def primes(n_max):
|
|||||||
|
|
||||||
:param n_max:
|
:param n_max:
|
||||||
"""
|
"""
|
||||||
try:
|
b = Bitarray(n_max)
|
||||||
import bitarray
|
b.setall(True)
|
||||||
b = bitarray.bitarray(n_max)
|
|
||||||
b.setall(True)
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
b = [True for _ in range(n_max)]
|
|
||||||
n = 1
|
n = 1
|
||||||
b[n - 1] = False
|
b[n - 1] = False
|
||||||
while n * n <= n_max:
|
while n * n <= n_max:
|
||||||
|
|||||||
Reference in New Issue
Block a user