Brute force

First, we need to know when the multiplicand/multiplier/product triplet is pandigital. There are several ways to do this, probably the most obvious being to convert the triplet to a single sorted string and compare it to "123456789".

From solution1.py:

def is_pandigital(multiplicand, multiplier, product):
    return sorted(str(multiplicand) + str(multiplier) + str(product)) == list("123456789")

One solution I really like uses a binary number to keep track of the digits. This is faster than converting the triplet to a string and uses less memory than a set or list. This method uses the bits as flags to check if a digit is present. If one of the digits is used twice, the triplet is not pandigital. If the final binary number is 0b1111111110, the triplet is pandigital.

def is_pandigital3(multiplicand, multiplier, product):
    digits = 0
    for n in (multiplicand, multiplier, product):
        while n:
            if digits & (1 << (n % 10)):
                return False
            digits |= 1 << (n % 10)
            n //= 10

    return digits == 0b1111111110

Next, we need to find all the possible multiplicand/multiplier/product combinations. We can do this by brute force, trying all the possible values for the multiplicand and multiplier from 1 to 987654321. But the calculation will take too long.

We know that if the multiplier is 5 digits, then the result will be at least 5 digits, so the total number of digits will be at least 11 and therefore not pandigital.

On the contrary, if the multiplier is 1 digit and the multiplicand 3 digits, the result will be 4 digits and the total number of digits will be 8.

Trying different combinations of multiplicand and multiplier, we find that only the following one result in a 9-digit triplet.

  • 2 digits * 3 digits = product of 4 or 5 digits
  • 1 digit * 4 digits = product of 4 or 5 digits

We can limit the search to these combinations. To avoid duplicates, we can store the current pandigital products in a set and compute the sum at the end.

From solution1.py:

def pandigital_products():
    products = set()
    for i in range(1, 100):
        for j in range(100 if i > 9 else 1000, 10000 // i + 1):
            if is_pandigital3(i, j, i * j):
                products.add(i * j)

    return sum(products)