mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-12-25 04:30:15 +00:00
112 lines
2.9 KiB
Python
112 lines
2.9 KiB
Python
|
"""
|
||
|
https://projecteuler.net/problem=51
|
||
|
Prime digit replacements
|
||
|
Problem 51
|
||
|
|
||
|
By replacing the 1st digit of the 2-digit number *3, it turns out that six of
|
||
|
the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.
|
||
|
|
||
|
By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit
|
||
|
number is the first example having seven primes among the ten generated numbers,
|
||
|
yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993.
|
||
|
Consequently 56003, being the first member of this family, is the smallest prime
|
||
|
with this property.
|
||
|
|
||
|
Find the smallest prime which, by replacing part of the number (not necessarily
|
||
|
adjacent digits) with the same digit, is part of an eight prime value family.
|
||
|
"""
|
||
|
|
||
|
from collections import Counter
|
||
|
from typing import List
|
||
|
|
||
|
|
||
|
def prime_sieve(n: int) -> List[int]:
|
||
|
"""
|
||
|
Sieve of Erotosthenes
|
||
|
Function to return all the prime numbers up to a certain number
|
||
|
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
||
|
|
||
|
>>> prime_sieve(3)
|
||
|
[2]
|
||
|
|
||
|
>>> prime_sieve(50)
|
||
|
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
|
||
|
"""
|
||
|
is_prime = [True] * n
|
||
|
is_prime[0] = False
|
||
|
is_prime[1] = False
|
||
|
is_prime[2] = True
|
||
|
|
||
|
for i in range(3, int(n ** 0.5 + 1), 2):
|
||
|
index = i * 2
|
||
|
while index < n:
|
||
|
is_prime[index] = False
|
||
|
index = index + i
|
||
|
|
||
|
primes = [2]
|
||
|
|
||
|
for i in range(3, n, 2):
|
||
|
if is_prime[i]:
|
||
|
primes.append(i)
|
||
|
|
||
|
return primes
|
||
|
|
||
|
|
||
|
def digit_replacements(number: int) -> List[List[int]]:
|
||
|
"""
|
||
|
Returns all the possible families of digit replacements in a number which
|
||
|
contains at least one repeating digit
|
||
|
|
||
|
>>> digit_replacements(544)
|
||
|
[[500, 511, 522, 533, 544, 555, 566, 577, 588, 599]]
|
||
|
|
||
|
>>> digit_replacements(3112)
|
||
|
[[3002, 3112, 3222, 3332, 3442, 3552, 3662, 3772, 3882, 3992]]
|
||
|
"""
|
||
|
number = str(number)
|
||
|
replacements = []
|
||
|
digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
|
||
|
|
||
|
for duplicate in Counter(number) - Counter(set(number)):
|
||
|
family = [int(number.replace(duplicate, digit)) for digit in digits]
|
||
|
replacements.append(family)
|
||
|
|
||
|
return replacements
|
||
|
|
||
|
|
||
|
def solution(family_length: int = 8) -> int:
|
||
|
"""
|
||
|
Returns the solution of the problem
|
||
|
|
||
|
>>> solution(2)
|
||
|
229399
|
||
|
|
||
|
>>> solution(3)
|
||
|
221311
|
||
|
"""
|
||
|
numbers_checked = set()
|
||
|
|
||
|
# Filter primes with less than 3 replaceable digits
|
||
|
primes = {
|
||
|
x for x in set(prime_sieve(1_000_000)) if len(str(x)) - len(set(str(x))) >= 3
|
||
|
}
|
||
|
|
||
|
for prime in primes:
|
||
|
if prime in numbers_checked:
|
||
|
continue
|
||
|
|
||
|
replacements = digit_replacements(prime)
|
||
|
|
||
|
for family in replacements:
|
||
|
numbers_checked.update(family)
|
||
|
primes_in_family = primes.intersection(family)
|
||
|
|
||
|
if len(primes_in_family) != family_length:
|
||
|
continue
|
||
|
|
||
|
return min(primes_in_family)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
print(solution())
|