1
|
|
|
""" |
2
|
|
|
Project Euler Problem 41: Pandigital Prime |
3
|
|
|
========================================== |
4
|
|
|
|
5
|
|
|
.. module:: solutions.problem41 |
6
|
|
|
:synopsis: My solution to problem #41. |
7
|
|
|
|
8
|
|
|
The source code for this problem can be |
9
|
|
|
`found here <https://bitbucket.org/nekedome/project-euler/src/master/solutions/problem41.py>`_. |
10
|
|
|
|
11
|
|
|
Problem Statement |
12
|
|
|
################# |
13
|
|
|
|
14
|
|
|
We shall say that an :math:`n`-digit number is pandigital if it makes use of all the digits :math:`1` to :math:`n` |
|
|
|
|
15
|
|
|
exactly once. For example, :math:`2143` is a :math:`4`-digit pandigital and is also prime. |
16
|
|
|
|
17
|
|
|
What is the largest :math:`n`-digit pandigital prime that exists? |
18
|
|
|
|
19
|
|
|
Solution Discussion |
20
|
|
|
################### |
21
|
|
|
|
22
|
|
|
First, observe that a decimal representation is assumed, so, only integers up to nine digits in length need be |
|
|
|
|
23
|
|
|
considered. However, the search space may be reduced even further by observing that some :math:`n`-digit pandigital |
|
|
|
|
24
|
|
|
patterns cannot possibly be prime. In particular, by enumeration of all pandigital numbers for a given :math:`n` or by |
|
|
|
|
25
|
|
|
the application of rules of divisibility. |
26
|
|
|
|
27
|
|
|
**Case: 1-digit pandigital (by enumeration)** |
28
|
|
|
|
29
|
|
|
:math:`1` is not prime |
30
|
|
|
:raw-html:`<br />` |
31
|
|
|
:math:`\\therefore` no :math:`1`-digit pandigital number is prime |
32
|
|
|
|
33
|
|
|
**Case: 2-digit pandigital (by enumeration)** |
34
|
|
|
|
35
|
|
|
:math:`12 = 2^2 \\times 3` is not prime |
36
|
|
|
:raw-html:`<br />` |
37
|
|
|
:math:`21 = 3 \\times 7` is not prime |
38
|
|
|
:raw-html:`<br />` |
39
|
|
|
:math:`\\therefore` no :math:`2`-digit pandigital number is prime |
40
|
|
|
|
41
|
|
|
**Case: 3-digit pandigital (by rules of divisibility)** |
42
|
|
|
|
43
|
|
|
Observe that any such number must contain the digits :math:`1,2,3` |
44
|
|
|
:raw-html:`<br />` |
45
|
|
|
Now, observe that :math:`1 + 2 + 3 = 6`, which is divisible by :math:`3` |
46
|
|
|
:raw-html:`<br />` |
47
|
|
|
:math:`\\Rightarrow` any :math:`3`-digit pandigital is divisible by :math:`3` |
48
|
|
|
:raw-html:`<br />` |
49
|
|
|
:math:`\\therefore` no :math:`3`-digit pandigital number is prime |
50
|
|
|
|
51
|
|
|
**Case: 5-digit pandigital (by rules of divisibility)** |
52
|
|
|
|
53
|
|
|
Observe that any such number must contain the digits :math:`1,2,3,4,5` |
54
|
|
|
:raw-html:`<br />` |
55
|
|
|
Now, observe that :math:`1 + 2 + 3 + 4 + 5 = 15` which is divisible by :math:`3` |
56
|
|
|
:raw-html:`<br />` |
57
|
|
|
:math:`\\Rightarrow` any :math:`5`-digit pandigital is divisible by :math:`3` |
58
|
|
|
:raw-html:`<br />` |
59
|
|
|
:math:`\\therefore` no :math:`5`-digit pandigital number is prime |
60
|
|
|
|
61
|
|
|
**Case: 6-digit pandigital (by rules of divisibility)** |
62
|
|
|
|
63
|
|
|
Observe that any such number must contain the digits :math:`1,2,3,4,5,6` |
64
|
|
|
:raw-html:`<br />` |
65
|
|
|
Now, observe that :math:`1 + 2 + 3 + 4 + 5 + 6 = 21` which is divisible by :math:`3` |
66
|
|
|
:raw-html:`<br />` |
67
|
|
|
:math:`\\Rightarrow` any :math:`6`-digit pandigital is divisible by :math:`3` |
68
|
|
|
:raw-html:`<br />` |
69
|
|
|
:math:`\\therefore` no :math:`6`-digit pandigital number is prime |
70
|
|
|
|
71
|
|
|
**Case: 8-digit pandigital (by rules of divisibility)** |
72
|
|
|
|
73
|
|
|
Observe that any such number must contain the digits :math:`1,2,3,4,5,6,7,8` |
74
|
|
|
:raw-html:`<br />` |
75
|
|
|
Now, observe that :math:`1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 = 36` which is divisible by :math:`3` |
76
|
|
|
:raw-html:`<br />` |
77
|
|
|
:math:`\\Rightarrow` any :math:`8`-digit pandigital is divisible by :math:`3` |
78
|
|
|
:raw-html:`<br />` |
79
|
|
|
:math:`\\therefore` no :math:`8`-digit pandigital number is prime |
80
|
|
|
|
81
|
|
|
**Case: 9-digit pandigital (by rules of divisibility)** |
82
|
|
|
|
83
|
|
|
Observe that any such number must contain the digits :math:`1,2,3,4,5,6,7,8,9` |
84
|
|
|
:raw-html:`<br />` |
85
|
|
|
Now, observe that :math:`1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45` which is divisible by :math:`3` |
86
|
|
|
:raw-html:`<br />` |
87
|
|
|
:math:`\\Rightarrow` any :math:`9`-digit pandigital is divisible by :math:`3` |
88
|
|
|
:raw-html:`<br />` |
89
|
|
|
:math:`\\therefore` no :math:`9`-digit pandigital number is prime |
90
|
|
|
|
91
|
|
|
So, we only need to consider :math:`4`-digit and :math:`7`-digit numbers. |
92
|
|
|
|
93
|
|
|
Originally, my solution enumerated primes up to (and including) :math:`7`-digits and then checked whether each prime is |
|
|
|
|
94
|
|
|
:math:`n`-digit pandigital. While this algorithm produces the correct answer, we can do better. The runtime of this |
|
|
|
|
95
|
|
|
algorithm is dominated by the cost of prime sieving. |
96
|
|
|
|
97
|
|
|
My second, superior, solution enumerates :math:`n`-digit pandigital numbers and checks whether they are prime. This |
|
|
|
|
98
|
|
|
solution is faster because there are generally less pandigital numbers than primes for the same number of digits (at |
|
|
|
|
99
|
|
|
least for the search interval considered): |
100
|
|
|
|
101
|
|
|
- The number of :math:`7`-digit primes is about :math:`\\frac{10^7}{\\log(10^7)} \\approx 620420` |
102
|
|
|
- The number of :math:`7`-digit pandigital numbers is precisely :math:`7! = 5040` |
103
|
|
|
|
104
|
|
|
Solution Implementation |
105
|
|
|
####################### |
106
|
|
|
|
107
|
|
|
.. literalinclude:: ../../solutions/problem41.py |
108
|
|
|
:language: python |
109
|
|
|
:lines: 112- |
110
|
|
|
""" |
111
|
|
|
|
112
|
|
|
from itertools import chain |
113
|
|
|
|
114
|
|
|
from lib.numbertheory import is_probably_prime |
115
|
|
|
from lib.sequence import Pandigitals |
116
|
|
|
|
117
|
|
|
|
118
|
|
|
def solve(): |
119
|
|
|
""" Compute the answer to Project Euler's problem #41 """ |
120
|
|
|
answer = 0 |
121
|
|
|
for candidate in chain(Pandigitals(n=4), Pandigitals(n=7)): |
122
|
|
|
if is_probably_prime(candidate): |
123
|
|
|
answer = max(answer, candidate) # the n-digit pandigital is also prime |
124
|
|
|
return answer |
125
|
|
|
|
126
|
|
|
|
127
|
|
|
expected_answer = 7652413 |
|
|
|
|
128
|
|
|
|
This check looks for lines that are too long. You can specify the maximum line length.