-
Notifications
You must be signed in to change notification settings - Fork 1
/
p68.ts
85 lines (78 loc) · 2.46 KB
/
p68.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// AssemblyScript solution for Project Euler problem 68
/** Test for "magic" (as defined in the problem statement) */
function isMagic(sides: u8, arrangement: Array<u8>): bool {
let expected: u8 = 0;
for (let i: u8 = 0; i < sides; i++) {
// Check the sum on this line
const sum = arrangement[i] + arrangement[(i + 1) % sides] + arrangement[i + sides];
if (expected > 0) {
if (sum !== expected) {
// Sum doesn't match previous sum; result: not magic
return false;
}
} else {
expected = sum;
}
}
// All sums were equal; result: magic
return true;
}
/** Create a number out of the digit string (with special handling for 10) */
function concatenate(sides: u8, arrangement: Array<u8>): u64 {
// Find lowest external node
let lowest = sides * 2;
let lowestIndex = 0;
for (let i: u8 = 0; i < sides; i++) {
const value = arrangement[i + sides];
if (value < lowest) {
lowest = value;
lowestIndex = i;
}
}
let result: u64 = 0;
for (let i: u8 = 0; i < sides; i++) {
const index = (lowestIndex + i) % sides;
const offsets = [index + sides, index, (index + 1) % sides];
for (let j = 0; j < offsets.length; j++) {
const value = arrangement[offsets[j]];
result *= (value < 10) ? 10 : 100;
result += value;
}
}
return result;
}
/** Recursive function to test permutations and, if valid, return the best value */
function recurse(sides: u8, arrangement: Array<u8>, position: u8, remaining: u16): u64 {
const n = sides * 2;
if (position >= n) {
// Permutation is complete; test it
if (isMagic(sides, arrangement)) {
return concatenate(sides, arrangement);
} else {
return 0;
}
} else {
// Still building permutation
let best: u64 = 0;
for (let i: u8 = 0; i < n; i++) {
const bit: u16 = 1 << i;
if (remaining & bit) {
// Also need to ensure that 10 isn't in an internal node (because that would result in a
// 17-digit string, which is explicitly disallowed in the problem statement)
if ((i + 1) < 10 || (position > sides)) {
arrangement[position] = i + 1;
const result = recurse(sides, arrangement, position + 1, remaining & ~bit);
if (result > best) {
best = result;
}
}
}
}
return best;
}
}
/** Main entry point */
export function solve(): u64 {
const sides: u8 = 5;
return recurse(sides, new Array<u8>(sides * 2), 0, ~0);
}