70 lines
2.2 KiB
JavaScript
70 lines
2.2 KiB
JavaScript
const fs = require('fs');
|
|
const data = fs.readFileSync('input.txt', 'utf-8');
|
|
const lines = data.split('\n').map(num => parseInt(num)).sort((a,b)=>(a-b));
|
|
lines.unshift(0);
|
|
lines.push(lines[lines.length-1]+3);
|
|
|
|
|
|
// convert to linked list
|
|
let last = {};
|
|
let i = 0
|
|
do {
|
|
let entry = {
|
|
value: lines[i],
|
|
prev: last
|
|
};
|
|
last.next = entry;
|
|
last = entry;
|
|
i++;
|
|
} while (i < lines.length)
|
|
|
|
// find removeable adaptors
|
|
let removeableAdaptors = [];
|
|
const lastVal = last
|
|
last = last.prev
|
|
while (last.prev) {
|
|
if (last.next.value - last.prev.value <= 3){
|
|
removeableAdaptors.push(last)
|
|
}
|
|
last = last.prev
|
|
}
|
|
|
|
// divide removeable adaptors into groups that don't interfere with one another when removed
|
|
// this changes the runtime with the given input from a over a month to less than a millisecond
|
|
// however, in a worst case scenareo, where every adaptor is removeable, this would still take trillions of years.
|
|
let adaptorGroups = []
|
|
function makeGroups(removeableAdaptors) {
|
|
for (let i = removeableAdaptors.length-1; i>-1; i--) {
|
|
// if the gap between two removeable adaptors > 2 then you know they will not intefere with each other
|
|
if (i == 0 || removeableAdaptors[i-1].value - removeableAdaptors[i].value > 2) {
|
|
adaptorGroups.push(removeableAdaptors.slice(i))
|
|
makeGroups(removeableAdaptors.slice(0, i))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
makeGroups(removeableAdaptors)
|
|
|
|
function findArrangements (removeableAdaptors, s = 0) {
|
|
total = 1
|
|
// for each adaptor in the group
|
|
for (let i = s; i < removeableAdaptors.length; i++){
|
|
// if you can remove this adaptor
|
|
if (removeableAdaptors[i].next.value-removeableAdaptors[i].prev.value <= 3) {
|
|
// remove the adaptor and find arrangements with it gone
|
|
removeableAdaptors[i].prev.next = removeableAdaptors[i].next
|
|
total += findArrangements (removeableAdaptors, i+1)
|
|
// add the adaptor back for following tests
|
|
removeableAdaptors[i].prev.next = removeableAdaptors[i]
|
|
}
|
|
}
|
|
return total
|
|
}
|
|
|
|
console.time('time')
|
|
// multipy the amount of arrangements in each group to get the total amount of arrangements.
|
|
answer = adaptorGroups.reduce((a, g) => {return a*findArrangements(g)},1)
|
|
console.timeEnd('time')
|
|
|
|
console.log(answer)
|