**This is our solution and implementation to problem #68 on Project Euler.**

Our code is written in TypeScript, a language which is built on-top of JavaScript and transpiles to it. We've included the problem statement, our code (which is commented for greater clarity), our video which outlines our analysis and implementation approach, and the solution + how long it took to calculate it.

**Note:** the code and contents here might be slightly different than what is in the video. We've made some improvements to some of the code since recording.

If you would like to view the original problem and solve it, please visit: Magic 5-Gon Ring on Project Euler. If you're having trouble solving this problem, or are just curious to see how others have solved it, feel free to take a look, but please put solid effort into solving this before viewing the actual solution to the problem.

### Problem Statement

Consider the following "magic" 3-gon ring, filled with the numbers 1 to 6, and each line adding to nine.

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.

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?

### Our Solution

Our solution is given in the TypeScript code below:

` ````
import { AbstractSolution, RunSolution } from "../../utils/solution";
@RunSolution
export class Solution68 extends AbstractSolution {
//cache to help with generating permutations
private choicesMap = new Map<string, number[][]>();
getProblemName(): string {
return "Magic 5-Gon Ring";
}
protected solve() {
//return this.getMaxMagic(6, 3, Infinity);
return this.getMaxMagic(10, 5, 16);
}
/***
* Map choices permutation to seq:
* :: 0, 1, 2
* :: 3, 2, 4
* :: 5, 4, 1
* Index is from choice permutation
*
*/
private getMaxMagic(upperNumber: number, numSums: number, maxLen: number): number {
const seqPerms = this.getValidSeqPerms(upperNumber);
const newAr = new Array(numSums * 3).fill(-1);
let maxNumber = 0;
for (let seqPermsIndex = 0; seqPermsIndex < seqPerms.length; seqPermsIndex++) {
const seqEntries = seqPerms[seqPermsIndex];
//convert the perms to a full sequence
const seq: number[] = [...newAr];
seq[0] = seqEntries[0];
seq[1] = seqEntries[1];
seq[2] = seqEntries[2];
const initialSum = seq[0] + seq[1] + seq[2];
seq[seq.length - 3] = seqEntries[seqEntries.length - 1];
seq[seq.length - 2] = seqEntries[seqEntries.length - 2];
seq[seq.length - 1] = seqEntries[1];
let isValid = seq[seq.length - 3] + seq[seq.length - 2] + seq[seq.length - 1] === initialSum;
for (let i = 3, seqOffset = 3; isValid && i < seqEntries.length - 1; i += 2, seqOffset += 3) {
seq[seqOffset] = seqEntries[i];
seq[seqOffset + 1] = seqEntries[i - 1];
seq[seqOffset + 2] = seqEntries[i + 1];
isValid = seq[seqOffset] + seq[seqOffset+1] + seq[seqOffset+2] === initialSum;
}
if (isValid) {
const seqStr = seq.join("");
if (seqStr.length <= maxLen) {
maxNumber = Math.max(
maxNumber,
parseInt(seqStr)
);
}
}
}
return maxNumber;
}
/**
* Get permutations and remove invalid options
* @param upperNumber
* @returns
*/
private getValidSeqPerms(upperNumber: number): number[][] {
const choices = new Array(upperNumber).fill(0)
.map((_, ind) => ind + 1);
let seqPerms = this.getNumPerms(choices);
//remove seq items if smallest leaf is not first
seqPerms = seqPerms.filter(seq => {
const first = seq[0];
let isGood = true;
for (let i = 3; isGood && i < seq.length; i += 2) {
isGood = (first < seq[i]);
}
return isGood;
});
return seqPerms;
}
/**
* Get permutations for each different choices lengths
* Uses caching to avoid redundant operations
* @param choices
* @returns
*/
private getNumPerms(choices: number[]): number[][] {
if (choices.length === 1) {
return [choices];
}
const key = choices.join("");
if (!this.choicesMap.has(key)) {
const perms: number[][] = [];
for (let i = 0; i < choices.length; i++) {
const remaining = choices.filter(item => item !== choices[i]);
const subChoices = this.getNumPerms(remaining);
subChoices.forEach(sc => {
perms.push([choices[i], ...sc]);
});
}
this.choicesMap.set(key, perms);
}
return this.choicesMap.get(key)!;
}
}
```

### Results

This implementation found the solution in **3399ms**.

If you would like to view the answer, click below to reveal. Please consider reviewing the implementation and trying to code your own solution before viewing the answer.

## View Answer

The answer is

**6531031914842725.**

All of our solutions are hosted on GitHub. The code on this page was pulled from the repo and the solution and execution time were calculated based on that code.