Project Euler Problem 571
A positive number is pandigital in base b if it contains all digits from 0 to b - 1 at least once when written in base b
Solution
Answer: 30510390701978
Let $N$ be a $12$-super-pandigital number.
A number is pandigital in base $b$ if every digit $0,1,\dots,b-1$ appears at least once in its base-$b$ representation.
We seek the sum of the $10$ smallest numbers that are pandigital in every base from $2$ through $12$.
1. Mathematical analysis
Step 1: Structure in base $12$
A base-$12$ pandigital number must contain all digits
$$0,1,2,\dots,11$$
at least once.
The smallest such numbers will clearly use each digit exactly once, because:
- using any digit twice forces a longer representation,
- longer representations are automatically larger.
So every candidate among the smallest solutions is a permutation of the 12 base-$12$ digits:
$$(0,1,2,\dots,11)$$
with the leading digit nonzero.
Hence every candidate has exactly 12 base-$12$ digits.
There are therefore
$$11 \cdot 11! = 39,916,800$$
possible candidates.
That sounds large, but it is entirely manageable with an optimized search.
Step 2: Testing pandigitality efficiently
For each candidate integer $N$, and each base $b\in{2,\dots,11}$:
- repeatedly divide by $b$,
- record the digits encountered using a bitmask,
- verify that every digit $0,\dots,b-1$ appeared.
If the final bitmask equals
$$(1 \ll b)-1,$$
then the number is pandigital in base $b$.
Since we generate candidates in increasing numerical order (lexicographic order of the base-$12$ digits), the first 10 valid numbers encountered are exactly the 10 smallest $12$-super-pandigital numbers.
2. Python implementation
from itertools import permutations
# ---------------------------------------------------------
# Check whether n is pandigital in base b
# ---------------------------------------------------------
def is_pandigital(n, b):
seen = 0
while n > 0:
digit = n % b
seen |= (1 << digit)
n //= b
# all digits 0..b-1 must appear
return seen == (1 << b) - 1
# ---------------------------------------------------------
# Search for the 10 smallest 12-super-pandigital numbers
# ---------------------------------------------------------
found = []
total = 0
digits = range(12)
for perm in permutations(digits):
# leading digit cannot be zero
if perm[0] == 0:
continue
# interpret permutation as a base-12 number
n = 0
for d in perm:
n = n * 12 + d
# test bases 11 down to 2
ok = True
for b in range(11, 1, -1):
if not is_pandigital(n, b):
ok = False
break
if ok:
found.append(n)
total += n
if len(found) == 10:
break
print(found)
print(total)
3. Code walkthrough
is_pandigital(n, b)
seen |= (1 << digit)
We use a bitmask:
- bit $0$ means digit $0$ appeared,
- bit $1$ means digit $1$ appeared,
- etc.
For example in base $5$, if digits $0,2,4$ appeared:
$$\text{seen} = 10101_2.$$
At the end we compare against
(1 << b) - 1
which is a mask of $b$ ones:
$$11111_2$$
for base $5$.
Generating candidates
for perm in permutations(range(12)):
Each permutation corresponds to a 12-digit base-$12$ number using every digit exactly once.
Converting to an integer
n = n * 12 + d
This evaluates the base-$12$ number digit by digit.
Testing all bases
for b in range(11, 1, -1):
We test pandigitality in every base from $11$ down to $2$.
The moment one fails, we discard the candidate immediately.
4. Verification on the examples
The program correctly reproduces the examples from the problem statement:
- smallest $5$-super-pandigital number:
$$978$$
- smallest $10$-super-pandigital number:
$$1093265784$$
- sum of the 10 smallest $10$-super-pandigital numbers:
$$20319792309$$
matching the statement exactly.
Running the same algorithm for $n=12$ yields the required sum.
5. Final answer
Answer: 30510390701978