The problem: https://projecteuler.net/problem=43
The idea here is to try all the possibilities, but with clever prunning.
Some obvious properties we must consider:
by_11 = 0
by_13 = 0
by_17 = 0
for n in range(100, 1000):
d = n%10
dd = (n//10)%10
ddd = (n//100)
if d == dd or dd == ddd or d == ddd:
continue
if n % 11 == 0:
by_11 += 1
if n % 13 == 0:
by_13 += 1
if n % 17 == 0:
by_17 += 1
print(11, by_11)
print(13, by_13)
print(17, by_17)
Not just that, the five digit number $d_6 d_7 d_8 d_9 d_{10}$ has its ending part as one of the 39; its middle part as one of the 50 and its initial part as one of the 64. Our first task will be, then, to find out the possible last 5 digits based on the criteria we've gotten so far.
import itertools
def numeric_val(digits):
n = 0
for d in digits:
n *= 10
n += d
return n
possible_endings = []
all_digits = list(range(0, 10))
for d6 in [0, 5]:
for perm in itertools.permutations(all_digits, 4):
if d6 in perm:
continue
digits = [d6]
digits.extend(perm)
n1 = numeric_val(digits[0:3])
if n1 % 11 != 0:
continue
n2 = numeric_val(digits[1:4])
if n2 % 13 != 0:
continue
n3 = numeric_val(digits[2:5])
if n3 % 17 != 0:
continue
possible_endings.append(digits)
print(len(possible_endings))
print(possible_endings)
Success. There are very few of them. This will help with the prunning.
s = 0
all_of_them = []
for ending in possible_endings:
digits = []
for d in all_digits:
if d not in ending:
digits.append(d)
for perm in itertools.permutations(digits, 5):
cand = list(perm)
cand.extend(ending)
n1 = numeric_val(cand[1:4])
if n1 % 2 != 0:
continue
n2 = numeric_val(cand[2:5])
if n2 % 3 != 0:
continue
n3 = numeric_val(cand[3:6])
if n3 % 5 != 0:
continue
n4 = numeric_val(cand[4:7])
if n4 % 7 != 0:
continue
n = numeric_val(cand)
s += n
all_of_them.append(n)
print("Sum is", s)
print("There are", len(all_of_them), "of them.")
print("They are:", all_of_them)