https://projecteuler.net/problem=43
The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a rather interesting sub-string divisibility property.
Let $d_1$ be the 1st digit, $d_2$ be the 2nd digit, and so on. In this way, we note the following:
$d_2d_3d_4$=406 is divisible by 2
$d_3d_4d_5$=063 is divisible by 3
$d_4d_5d_6$=635 is divisible by 5
$d_5d_6d_7=357$ is divisible by 7
$d_6d_7d_8=572$ is divisible by 11
$d_7d_8d_9=728$ is divisible by 13
$d_8d_9d_{10} =289$ is divisible by 17
Find the sum of all 0 to 9 pandigital numbers with this property.
We write a function that tests for the sub-string divisibility property. Then we simply brute force.
def is_sub_string_divisible(s):
s = "".join(s)
if int(s[1:4]) % 2 != 0:
return False
if int(s[2:5]) % 3 != 0:
return False
if int(s[3:6]) % 5 != 0:
return False
if int(s[4:7]) % 7 != 0:
return False
if int(s[5:8]) % 11 != 0:
return False
if int(s[6:9]) % 13 != 0:
return False
if int(s[7:10]) % 17 != 0:
return False
return True
assert(is_sub_string_divisible("1406357289"))
assert(is_sub_string_divisible("1406357298") == False)
import itertools
s = sum([int("".join(p)) for p in itertools.permutations("0123456789") if is_sub_string_divisible(p)])
print(s)
assert(s == 16695334890)
I just want to write my own permutations functions to see that I am able to do it quickly. We pick each element once and combine it with the permutations for the remaining items:
def permutations(items):
items = list(items)
if not items:
return [[]]
perms = []
for item in items:
items_new = list(items)
items_new.remove(item)
permutations_new = permutations(items_new)
for perm in permutations_new:
perms.append([item] + perm)
return perms
assert(permutations([]) == [[]])
assert(permutations([1]) == [[1]])
assert(permutations([1,2]) == [[1,2], [2,1]])
assert(permutations([1,2,3]) == [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]])