Yet another exciting math problem that requires an algorithmic approach to arrive at a quick solution! There is a pen-paper approach to it too, but this post assumes we’re more interested in discussing the programming angle.
First, the problem:
Working clockwise, and starting from the group of three with the numerically lowest external node (4,3,2 in this example), each solution can be described uniquely. For example, the above solution can be described by the set: 4,3,2; 6,2,1; 5,1,3.
It is possible to complete the ring with four different totals: 9, 10, 11, and 12. There are eight solutions in total.
Total Solution Set:
9 4,2,3; 5,3,1; 6,1,2
9 4,3,2; 6,2,1; 5,1,3
10 2,3,5; 4,5,1; 6,1,3
10 2,5,3; 6,3,1; 4,1,5
11 1,4,6; 3,6,2; 5,2,4
11 1,6,4; 5,4,2; 3,2,6
12 1,5,6; 2,6,4; 3,4,5
12 1,6,5; 3,5,4; 2,4,6
By concatenating each group it is possible to form 9-digit strings; the maximum string for a 3-gon ring is 432621513.
Problem
Using the numbers 1 to 10, and depending on arrangements, it is possible to form 16- and 17-digit strings. What is the maximum 16-digit string for a “magic” 5-gon ring?
Algorithm
In attempting this problem, I choose to label the 5 inner nodes as i, j, k, l, and m.
α, β, γ, δ, and θ being the corresponding outer nodes.
Let x be the sum total of each triplet line, i.e.,
x = α + i + j = β + j + k = γ + k + l = δ + l + m = θ + m + i
First Observation:
For the string to be 16-digits, 10 has to be in the outer ring, as each number in the inner ring is included in the string twice. Next, we fill the inner ring in an iterative manner.
Second Observation:
There 9 numbers to choose from for the inner ring — 1, 2, 3, 4, 5, 6, 7, 8 and 9.
5 have to be chosen. This can be done in 9C5 = 126 ways.
According to circular permutation, if there are n distinct numbers to be arranged in a circle, this can be done in (n-1)! ways, where (n-1)! = (n-1).(n-2).(n-3)…3.2.1. So 5 distinct numbers can be arranged in 4! permutations, i.e., in 24 ways around a circle, or pentagonal ring, to be more precise.
So in all, this problem can be solved in 126×24 = 3024 iterations.
Third Observation:
For every possible permutation of an inner-ring arrangement, there can be one or more values of x (triplet line-sum) that serve as a possible contenders for a “magic” string whose triplets add up to the same number, x. To ensure this, we only need that the values of α through θ of the outer ring are distinct, different from the inner ring, with the greatest of these equal to 10.
Depending on the relative positioning of the numbers in the inner ring, one can narrow the range of x-values one might have to check for each permutation. To zero-down on such a range, let’s look at an example. Shown in the figure below is a randomly chosen permutation of number in the inner ring – 7, 2, 3, 4 and 5, in that order.
So 10, 9, 8, 6 and 1 must fill the outer circle. It’s easy to notice that the 5, 7 pair is the greatest adjacent pair. So whatever x is, it has to be at least 5 + 7 + 1 = 13 (1 being the smallest number of the outer ring). Likewise, 2, 3 is the smallest adjacent pair, so whatever x is, it can’t be any more than 2 + 3+ 10 = 15 (10 being the largest number of the outer ring). This leaves us with a narrow range of x-values to check – 13, 14 and 15.
Next, we arrange the 5 triplets in clock-wise direction starting with the triplet with the smallest number in the outer ring to form a candidate string. This exercise when done for each of the 3024 permutations will shortlist a range of candidates, of which, the maximum is chosen.
That’s all there is to the problem!
Here’s the Python Code. It executes in about a tenth of a second!
from itertools import permutations | |
from itertools import combinations | |
# array of candidate solutions empty at the beginning | |
record = [] | |
# choose 5 numbers for inner cells between 1 and 9; there are 9C5 combinations | |
# the problem ask for a 16-digit number, so 10 is not to be included in inner cells | |
cells = range(1,10) | |
inner_cells = [map(int,comb) for comb in combinations(cells,5)] | |
# code to calculate min and max couple in an array | |
def minCouple(array): | |
answer = array[0]+array[-1] | |
for i in xrange(len(array)-1): | |
coupleSum = array[i] + array[i+1] | |
if coupleSum < answer: | |
answer = coupleSum | |
return answer | |
def maxCouple(array): | |
answer = 0 | |
for i in xrange(len(array)-1): | |
if i==0: | |
coupleSum = array[0]+ array[-1] | |
if coupleSum > answer: | |
answer = coupleSum | |
else: | |
coupleSum = array[i]+ array[i+1] | |
if coupleSum > answer: | |
answer = coupleSum | |
return answer | |
# Algorithm | |
for array in inner_cells: | |
pivot = array[0] | |
perm_array = array[1:] | |
perms = [map(int,perm) for perm in permutations(perm_array,4)] | |
for perm in perms: | |
checkArray = perm | |
checkArray.insert(0,pivot) | |
outerRing = [el for el in range(1,11) if el not in checkArray] | |
xMax = minCouple(checkArray) + max(outerRing) | |
xMin = maxCouple(checkArray) + min(outerRing) | |
if xMax >= xMin: | |
for x in xrange(xMin, xMax+1): | |
i = checkArray[0] | |
j = checkArray[1] | |
k = checkArray[2] | |
l = checkArray[3] | |
m = checkArray[4] | |
alpha = x-i-j | |
beta = x-j-k | |
gamma = x-k-l | |
delta = x-l-m | |
theta = x-m-i | |
outerCalculated = [alpha, beta, gamma, delta, theta] | |
if sorted(outerCalculated) == sorted(outerRing): | |
a = [alpha, i, j] | |
b = [beta, j, k] | |
c = [gamma, k, l] | |
d = [delta, l, m] | |
e = [theta, m, i] | |
min_val = min(alpha, beta, gamma, delta, theta) | |
if alpha == min_val: | |
append = a+b+c+d+e | |
elif beta == min_val: | |
append = b+c+d+e+a | |
elif gamma == min_val: | |
append = c+d+e+a+b | |
elif delta == min_val: | |
append = d+e+a+b+c | |
elif theta == min_val: | |
append = e+a+b+c+d | |
l = [str(i) for i in append] | |
s = ''.join(l) | |
integer_list = int(s) | |
record.append(integer_list) | |
print max(record) |
Ans: 6531031914842725