88 lines
2.1 KiB
JavaScript
88 lines
2.1 KiB
JavaScript
|
const fs = require('fs/promises');
|
||
|
|
||
|
const sum = (arr) => arr.reduce((total, num) => total+num, 0);
|
||
|
const arrayOfLength = n => Array.from(Array(n).keys()).map(() => {});
|
||
|
|
||
|
const createNode = (str) => {
|
||
|
const stats = str.match(/Valve ([A-Z]+) has flow rate=([\d]+); tunnels? leads? to valves? (.*)$/);
|
||
|
if(!stats) {
|
||
|
console.log("Bad line? : ", str);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const id = stats[1];
|
||
|
const rate = stats[2];
|
||
|
const edges = stats[3].split(', ');
|
||
|
|
||
|
return {
|
||
|
id,
|
||
|
rate,
|
||
|
edges,
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
const main = async () => {
|
||
|
const input = (await fs.readFile("./input.txt", 'utf8')).split("\n").slice(0, -1).sort();
|
||
|
|
||
|
const nodesById = {};
|
||
|
|
||
|
for(const row of input) {
|
||
|
const node = createNode(row);
|
||
|
if(!node) continue;
|
||
|
nodesById[node.id] = node;
|
||
|
}
|
||
|
|
||
|
const nodesByRate = Object.values(nodesById).sort((a, b) => b.rate - a.rate).filter(n => n.rate > 0);
|
||
|
console.log("nodes by rate: ", nodesByRate);
|
||
|
|
||
|
|
||
|
const findEachOptimalPath = (node, queue = [], visited = {}, length = 0) => {
|
||
|
visited[node.id] = length;
|
||
|
for(const edge of node.edges) {
|
||
|
const neighbor = nodesById[edge];
|
||
|
if(typeof visited[neighbor.id] === "undefined") {
|
||
|
queue.push(() => findEachOptimalPath(neighbor, queue, visited, length + 1));
|
||
|
}
|
||
|
};
|
||
|
if(queue.length) {
|
||
|
return queue.shift()();
|
||
|
}
|
||
|
return visited;
|
||
|
};
|
||
|
|
||
|
|
||
|
const valvePossibilities = Object.values(nodesById).reduce((possibilities, node) => {
|
||
|
possibilities[node.id] = findEachOptimalPath(node);
|
||
|
return possibilities;
|
||
|
}, {});
|
||
|
|
||
|
let best = 0;
|
||
|
|
||
|
const plan = (node, value, opened = {}, time = 30) => {
|
||
|
if(node.rate > 0 && time > 0) {
|
||
|
time = time - 1;
|
||
|
opened[node.id] = true;
|
||
|
value = value + time * node.rate;
|
||
|
}
|
||
|
|
||
|
if(value > best) {
|
||
|
best = value;
|
||
|
console.log(`${best} is better!`);
|
||
|
}
|
||
|
|
||
|
const distances = valvePossibilities[node.id];
|
||
|
for(const next of nodesByRate.filter(n => !opened[n.id])) {
|
||
|
const distance = distances[next.id];
|
||
|
if(time > distance + 1) {
|
||
|
plan(next, value, {...opened}, time - distances[next.id]);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
plan(nodesById["AA"], 0);
|
||
|
console.log("Answer is: ", best);
|
||
|
}
|
||
|
|
||
|
main();
|