From fd4ff495d99dcb611aff57ca00d3b9c0d570d95f Mon Sep 17 00:00:00 2001 From: felixm Date: Sun, 1 Oct 2023 20:19:41 +0200 Subject: [PATCH] Solve problem 111 and fix bug in lib prime. --- python/e111.py | 46 +++++++++++++++++++++++++++++++++++++++++++++ python/lib_prime.py | 7 ++++++- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 python/e111.py diff --git a/python/e111.py b/python/e111.py new file mode 100644 index 0000000..14137c2 --- /dev/null +++ b/python/e111.py @@ -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) diff --git a/python/lib_prime.py b/python/lib_prime.py index 4d194c4..1a11b30 100644 --- a/python/lib_prime.py +++ b/python/lib_prime.py @@ -68,6 +68,11 @@ def is_prime(n): 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 @@ -76,7 +81,7 @@ def is_prime_rabin_miller(number): s //= 2 r += 1 - for witness in [2, 3, 5, 7, 11, 13, 17, 23, 29, 31, 37, 41, 43, 47, 53]: + for witness in witnesses: remainder = pow(witness, s, number) if remainder == 1: continue