Skip to content

Commit

Permalink
Solve p51 in python (82nd solved!)
Browse files Browse the repository at this point in the history
  • Loading branch information
LivInTheLookingGlass committed Oct 17, 2024
1 parent 0941c8e commit e3f8490
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ Olivia's Project Euler Solutions
| | | | |Lu-Cov| |br| |
| | | | |LuaCheck| |
+------------+----------------------------+--------+-------------------+
| Python | CPython 3.6+ |br| | 81 | |Python| |br| |
| Python | CPython 3.6+ |br| | 82 | |Python| |br| |
| | Pypy 3.6+ |br| | | |Py-Cov| |br| |
| | GraalPy 23.1+ |br| | | |CodeQL| |br| |
| | Browser [#]_ | | |PythonLint| |
Expand Down
1 change: 1 addition & 0 deletions _data/answers.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ ID type size answer
48 int 64 9110846700
49 int 64 296962999629
50 int 32 997651
51 int 32 121313
52 int 32 142857
53 int 16 4075
55 uint 8 249
Expand Down
2 changes: 2 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ Problems Solved
+-----------+-----------+------------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`050`| | | | | | | |:py-d:`0050`| |
+-----------+-----------+------------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`051`| | | | | | | |:py-d:`0051`| |
+-----------+-----------+------------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`052`| | | | | | | |:py-d:`0052`| |
+-----------+-----------+------------+------------+------------+------------+------------+------------+------------+------------+
|:prob:`053`| | | | | | | |:py-d:`0053`|:rs-d:`0053`|
Expand Down
25 changes: 25 additions & 0 deletions docs/src/python/p0051.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Python Implementation of Problem 51
===================================

View source code :source:`python/src/p0051.py`

Includes
--------

- :py:func:`~python.src.lib.primes.is_prime`
- :external:py:func:`itertools.combinations`
- :external:py:func:`itertools.count`
- :external:py:func:`itertools.product`

Problem Solution
----------------

.. automodule:: python.src.p0051
:members:
:undoc-members:

.. literalinclude:: ../../../python/src/p0051.py
:language: python
:linenos:

.. tags:: prime-number, digit-manipulation
1 change: 1 addition & 0 deletions python/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ Problems Solved
- ☒ `48 <./src/p0048.py>`__
- ☒ `49 <./src/p0049.py>`__
- ☒ `50 <./src/p0050.py>`__
- ☒ `51 <./src/p0051.py>`__
- ☒ `52 <./src/p0052.py>`__
- ☒ `53 <./src/p0053.py>`__
- ☒ `55 <./src/p0055.py>`__
Expand Down
64 changes: 64 additions & 0 deletions python/src/p0051.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
Project Euler Problem 51
Again, surprised how effective the brute force solution was
Problem:
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 itertools import combinations, count, product
from typing import List, Tuple

from .lib.primes import is_prime

all_digits = tuple(str(x) for x in range(10))
non_zero = all_digits[1:]
endings = ("1", "3", "7", "9")


def main() -> int:
for L in count(5):
largest_possible: int = 10**L
for Ls in range(1, L - 1):
for indices in combinations(range(L - 1), Ls):
mask = ["d"] * L # d can be replaced by any digit
for index in indices:
mask[index] = "s" # s can be replaced by any single digit
valid, smallest = check_mask(mask, largest_possible, L, Ls)
if valid:
return smallest
return -1 # pragma: no cover


def check_mask(mask: List[str], largest_possible: int, L: int, Ls: int) -> Tuple[bool, int]:
for start, middle, end in product(non_zero, product(all_digits, repeat=(L - Ls - 2)), endings):
digits = (start, *middle, end)
current = mask.copy()
for digit in digits:
current[current.index("d")] = digit
valid = 0
smallest = largest_possible
if current[0] == "s":
selection = non_zero
else:
selection = all_digits
for s in selection:
new = [x if x != "s" else s for x in current]
num = int("".join(new))
if is_prime(num):
valid += 1
smallest = min(smallest, num)
elif 10 - int(s) + valid <= 8:
break
else:
return True, smallest
return False, 0
4 changes: 1 addition & 3 deletions python/test_euler.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@

answers: Dict[int, Union[int, str]] = {
x: get_answer(x) for x in (
*range(1, 51),
52,
53,
*range(1, 54),
*range(55, 61),
63,
67,
Expand Down

0 comments on commit e3f8490

Please sign in to comment.