Skip to content

Commit 0641338

Browse files
committed
Add project euler problem 51
1 parent ff9be86 commit 0641338

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

Diff for: project_euler/problem_51/__init__.py

Whitespace-only changes.

Diff for: project_euler/problem_51/sol1.py

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from collections import Counter
2+
3+
"""
4+
https://projecteuler.net/problem=51
5+
Prime digit replacements
6+
Problem 51
7+
8+
By replacing the 1st digit of the 2-digit number *3, it turns out that six of
9+
the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.
10+
11+
By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit
12+
number is the first example having seven primes among the ten generated numbers,
13+
yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993.
14+
Consequently 56003, being the first member of this family, is the smallest prime
15+
with this property.
16+
17+
Find the smallest prime which, by replacing part of the number (not necessarily
18+
adjacent digits) with the same digit, is part of an eight prime value family.
19+
"""
20+
21+
22+
def sieve(n: int) -> list:
23+
"""
24+
Sieve of Erotosthenes
25+
Function to return all the prime numbers up to a certain number
26+
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
27+
28+
>>> sieve(3)
29+
[2]
30+
31+
>>> sieve(50)
32+
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
33+
"""
34+
is_prime = [True] * n
35+
is_prime[0] = False
36+
is_prime[1] = False
37+
is_prime[2] = True
38+
39+
for i in range(3, int(n ** 0.5 + 1), 2):
40+
index = i * 2
41+
while index < n:
42+
is_prime[index] = False
43+
index = index + i
44+
45+
primes = [2]
46+
47+
for i in range(3, n, 2):
48+
if is_prime[i]:
49+
primes.append(i)
50+
51+
return primes
52+
53+
54+
def digit_replacements(number: int) -> list:
55+
"""
56+
Returns all the possible families of digit replacements in a number which
57+
contains at least one repeating digit
58+
59+
>>> digit_replacements(544)
60+
[[500, 511, 522, 533, 544, 555, 566, 577, 588, 599]]
61+
62+
>>> digit_replacements(3112)
63+
[[3002, 3112, 3222, 3332, 3442, 3552, 3662, 3772, 3882, 3992]]
64+
"""
65+
number = str(number)
66+
replacements = []
67+
digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
68+
69+
for duplicate in (Counter(number) - Counter(set(number))):
70+
family = [int(number.replace(duplicate, digit)) for digit in digits]
71+
replacements.append(family)
72+
73+
return replacements
74+
75+
76+
def solution() -> int:
77+
"""
78+
Returns the solution of the problem
79+
80+
>>> solution()
81+
121313
82+
"""
83+
numbers_checked = set()
84+
primes = set(sieve(1_000_000))
85+
86+
# Filter primes with less than 3 replacable digits
87+
primes = {x for x in primes if len(str(x)) - len(set(str(x))) >= 3}
88+
89+
for prime in primes:
90+
if prime in numbers_checked:
91+
continue
92+
93+
replacements = digit_replacements(prime)
94+
95+
for family in replacements:
96+
numbers_checked.update(family)
97+
primes_in_family = primes.intersection(family)
98+
99+
if len(primes_in_family) != 8:
100+
continue
101+
102+
return min(primes_in_family)
103+
104+
105+
if __name__ == "__main__":
106+
print(solution())

0 commit comments

Comments
 (0)