aboutsummaryrefslogtreecommitdiff
path: root/2022/16-proboscidea-volcanium/second.js
diff options
context:
space:
mode:
authorJulien Dessaux2022-12-26 07:48:55 +0100
committerJulien Dessaux2022-12-27 11:18:43 +0100
commitc9654e1ecc29eb124d5981726f33701cd70d1e1f (patch)
treebe8d526113d0d29ee2a3548176123d2425907f98 /2022/16-proboscidea-volcanium/second.js
parent2022-15 part 2 in zig (diff)
downloadadvent-of-code-c9654e1ecc29eb124d5981726f33701cd70d1e1f.tar.gz
advent-of-code-c9654e1ecc29eb124d5981726f33701cd70d1e1f.tar.bz2
advent-of-code-c9654e1ecc29eb124d5981726f33701cd70d1e1f.zip
2022-16 in js
Diffstat (limited to '')
-rw-r--r--2022/16-proboscidea-volcanium/second.js88
1 files changed, 88 insertions, 0 deletions
diff --git a/2022/16-proboscidea-volcanium/second.js b/2022/16-proboscidea-volcanium/second.js
new file mode 100644
index 0000000..18c6f84
--- /dev/null
+++ b/2022/16-proboscidea-volcanium/second.js
@@ -0,0 +1,88 @@
+import * as fs from "fs";
+import { PriorityQueue } from "./priority_queue.js";
+
+const regexp = /Valve ([A-Z]+) has flow rate=(\d+); tunnels? leads? to valves? ([A-Z, ]+)/;
+
+let valves = {};
+let uv = []; // useful valves
+
+fs.readFileSync("input", "utf8")
+ .trim()
+ .split("\n")
+ .map(line => {
+ let a = line.match(regexp);
+ valves[a[1]] = {
+ cost: undefined,
+ label: a[1],
+ links: a[3].split(", "),
+ rate: a[2],
+ computePathCostTo: function (target) {
+ Object.values(valves).forEach(v => v.cost = 0);
+ let nq = new PriorityQueue();
+ nq.enqueue(this, 0);
+ while (true) {
+ let n = nq.dequeue();
+ if (n.element.label === target) {
+ return n.element.cost + 1; // +1 to account for opening the valve
+ }
+ n.element.links.forEach(l => {
+ let v = valves[l];
+ if (v.cost === 0) {
+ v.cost = n.element.cost + 1;
+ nq.enqueue(v, v.cost);
+ }
+ });
+ }
+ },
+ };
+ if (a[2] > 0) {
+ uv.push(a[1]);
+ }
+ });
+
+
+let paths = {};
+uv.forEach(v => {
+ paths["AA"+v] = valves["AA"].computePathCostTo(v);
+ uv.forEach(w => {
+ if (v !== w) {
+ paths[v+w] = valves[v].computePathCostTo(w);
+ paths[w+v] = paths[v+w];
+ }
+ });
+});
+
+let max = 0;
+let parcours = [{current: "AA", actives: uv, steps: [], timeLeft: 26, pressure: 0}];
+for(let i=0; i<parcours.length; i++) {
+ let p = parcours[i];
+ p.pressure += valves[p.current].rate * p.timeLeft;
+ if (max < p.pressure) {
+ max = p.pressure;
+ }
+ p.actives.forEach(v => {
+ const cost = paths[p.current+v];
+ if (p.timeLeft - cost > 0) {
+ parcours.push({
+ current:v,
+ actives:p.actives.filter(f => f !== v), // this creates a shallow copy
+ steps: [...p.steps, v],
+ timeLeft: p.timeLeft - cost,
+ pressure: p.pressure,
+ });
+ }
+ });
+}
+parcours.sort((a, b) => b.pressure-a.pressure); // let's process all these paths and look for two that do not intersec and improve our max
+for (let i = 0; i < parcours.length; i++) {
+ if (parcours[i].pressure + parcours[0].pressure < max) continue;
+ for (let j = i+1; j < parcours.length; j++) {
+ if (parcours[i].pressure+parcours[j].pressure < max) continue;
+ if (parcours[i].steps.every(s => !parcours[j].steps.includes(s)))
+ if (parcours[i].pressure+parcours[j].pressure > max) {
+ max = parcours[i].pressure+parcours[j].pressure;
+ }
+ }
+}
+
+console.log(max);