Project Euler Problem 170
Take the number 6 and multiply it by each of 1273 and 9854: By concatenating these products we get the 1 to 9 pandigital
Solution
Answer: 9857164023
Let the integer multiplier be $m$, and let the other integers be $a_1,a_2,\dots,a_k$ with $k\ge2$.
We require:
- The concatenation of the inputs
$$m,a_1,a_2\cdots a_k$$
is a $0$-to-$9$ pandigital 10-digit number. 2. The concatenation of the products
$$(m a_1)(m a_2)\cdots(m a_k)$$
is also a $0$-to-$9$ pandigital 10-digit number.
We seek the largest possible concatenated product.
Mathematical Analysis
We want the lexicographically largest 10-digit pandigital number formed by concatenating the products.
Because the result is pandigital using digits $0$–$9$ exactly once, the first digit should be as large as possible, ideally $9$.
The brute-force search space appears enormous, but several structural observations reduce it drastically.
1. Structure of the concatenated product
Suppose:
$$P = \text{concat}(m a_1, m a_2,\dots,m a_k)$$
is the target pandigital number.
Since all digits $0$–$9$ appear exactly once in $P$, the total digit count is exactly 10.
Likewise,
$$I = \text{concat}(m,a_1,\dots,a_k)$$
must also be 10-digit pandigital.
Thus every digit from $0$ to $9$ appears exactly once among the inputs.
2. Key observation: partitioning digits
If we choose a permutation of digits $0$–$9$, we may partition it into pieces:
$$m,\ a_1,\ a_2,\dots,a_k$$
Then compute:
$$m a_1,\ m a_2,\dots,m a_k$$
and test whether their concatenation is another pandigital permutation.
This suggests a search over:
- permutations of digits,
- partitions into blocks.
But $10! = 3,628,800$, so we need pruning.
3. Maximizing the output
The concatenated product is compared numerically, hence lexicographically.
Therefore:
- we should generate candidate outputs in descending order,
- stop at the first valid one.
Instead of generating inputs first, it is much smarter to generate the output permutation in descending order.
4. Reconstructing the multiplier
Suppose the concatenated product is:
$$P = p_1p_2\dots p_{10}$$
We partition $P$ into chunks:
$$b_1,b_2,\dots,b_k$$
where each $b_i = m a_i$.
Then $m$ must divide every chunk.
Hence:
$$m = \gcd(b_1,b_2,\dots,b_k)$$
or at least a divisor of that gcd.
This becomes highly restrictive.
5. Efficient search strategy
We proceed as follows:
- Enumerate 10-digit pandigital numbers in descending order.
- Try every partition into at least two chunks.
- Compute the gcd of the chunks.
- Enumerate divisors $m>1$ of that gcd.
- Recover:
$$a_i = b_i/m$$ 6. Check whether concatenating
$$m,a_1,\dots,a_k$$
yields a 0–9 pandigital string.
The first valid output found is the maximum.
Python Implementation
from math import gcd
from itertools import permutations
DIGITS = "9876543210"
def is_pandigital_0_9(s):
"""Check whether s contains digits 0-9 exactly once."""
return len(s) == 10 and set(s) == set("0123456789")
def divisors(n):
"""Return all divisors of n greater than 1."""
ds = set()
d = 2
while d * d <= n:
if n % d == 0:
ds.add(d)
ds.add(n // d)
d += 1
ds.add(n)
return sorted(ds, reverse=True)
# Generate pandigital outputs in descending order
for perm in permutations(DIGITS):
s = ''.join(perm)
# Try all ways to partition into >=2 pieces
# There are 2^9 possible cut patterns
for mask in range(1, 1 << 9):
parts = []
start = 0
for i in range(9):
if mask & (1 << i):
parts.append(int(s[start:i+1]))
start = i + 1
parts.append(int(s[start:]))
# Need at least two multiplicands
if len(parts) < 2:
continue
# Compute gcd of all chunks
g = parts[0]
for x in parts[1:]:
g = gcd(g, x)
if g <= 1:
continue
# Try divisors of gcd as multiplier
for m in divisors(g):
inputs = []
ok = True
for x in parts:
if x % m != 0:
ok = False
break
inputs.append(str(x // m))
if not ok:
continue
candidate = str(m) + ''.join(inputs)
if is_pandigital_0_9(candidate):
print(s)
raise SystemExit
Code Walkthrough
Helper: pandigital test
def is_pandigital_0_9(s):
Checks that:
- length is exactly 10,
- digits are exactly ${0,1,\dots,9}$.
Helper: divisors
def divisors(n):
Returns divisors of $n$ greater than 1 in descending order.
We try larger multipliers first.
Generating candidate outputs
for perm in permutations(DIGITS):
Because DIGITS = "9876543210", permutations appear in descending lexicographic order.
Thus the first valid solution found is automatically maximal.
Partitioning the output
There are 9 possible cut positions between digits.
Each bitmask represents where cuts occur.
Example:
9857164023
with cuts after positions 3 and 7 gives:
985 | 7164 | 023
Recovering the multiplier
For chunks:
b1, b2, ...
the multiplier must divide every chunk.
Hence we compute:
g = gcd(...)
and test divisors of $g$.
Reconstructing inputs
If:
x = m * ai
then:
ai = x // m
We concatenate:
str(m) + ''.join(ai)
and verify this is also pandigital.
Small Example Verification
The example in the problem:
$$6 \times 1273 = 7638$$
$$6 \times 9854 = 59124$$
gives concatenated product:
$$763859124$$
and concatenated inputs:
$$612739854$$
both 1–9 pandigital.
Our algorithm generalizes exactly this logic to 0–9 pandigital numbers.
Final Verification
Running the program yields:
$$9857164023$$
Indeed:
$$27 \times 36508 = 985716$$
$$27 \times 149 = 4023$$
Concatenated product:
$$9857164023$$
Concatenated inputs:
$$2736508149$$
Both are 0–9 pandigital.
No larger pandigital concatenated product exists because the search proceeded in descending order and stopped at the first valid solution.
Answer: 9857164023