16.1 and 16.2
This commit is contained in:
parent
320b035125
commit
8080091870
4 changed files with 296 additions and 0 deletions
14
2022/16/example.txt
Normal file
14
2022/16/example.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
|
||||
Sensor at x=9, y=16: closest beacon is at x=10, y=16
|
||||
Sensor at x=13, y=2: closest beacon is at x=15, y=3
|
||||
Sensor at x=12, y=14: closest beacon is at x=10, y=16
|
||||
Sensor at x=10, y=20: closest beacon is at x=10, y=16
|
||||
Sensor at x=14, y=17: closest beacon is at x=10, y=16
|
||||
Sensor at x=8, y=7: closest beacon is at x=2, y=10
|
||||
Sensor at x=2, y=0: closest beacon is at x=2, y=10
|
||||
Sensor at x=0, y=11: closest beacon is at x=2, y=10
|
||||
Sensor at x=20, y=14: closest beacon is at x=25, y=17
|
||||
Sensor at x=17, y=20: closest beacon is at x=21, y=22
|
||||
Sensor at x=16, y=7: closest beacon is at x=15, y=3
|
||||
Sensor at x=14, y=3: closest beacon is at x=15, y=3
|
||||
Sensor at x=20, y=1: closest beacon is at x=15, y=3
|
87
2022/16/index.js
Normal file
87
2022/16/index.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
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();
|
135
2022/16/index2.js
Normal file
135
2022/16/index2.js
Normal file
|
@ -0,0 +1,135 @@
|
|||
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);
|
||||
|
||||
|
||||
const findEachOptimalPath = (node, queue = [], visited = {}, path = []) => {
|
||||
visited[node.id] = path;
|
||||
for(const edge of node.edges) {
|
||||
const neighbor = nodesById[edge];
|
||||
if(typeof visited[neighbor.id] === "undefined") {
|
||||
const nextPath = [...path, neighbor];
|
||||
queue.push(() => findEachOptimalPath(neighbor, queue, visited, nextPath));
|
||||
}
|
||||
};
|
||||
if(queue.length) {
|
||||
return queue.shift()();
|
||||
}
|
||||
return visited;
|
||||
};
|
||||
|
||||
|
||||
const valvePaths = Object.values(nodesById).reduce((possibilities, node) => {
|
||||
possibilities[node.id] = findEachOptimalPath(node);
|
||||
return possibilities;
|
||||
}, {});
|
||||
|
||||
|
||||
let best = 0;
|
||||
const bestPerTime = [];
|
||||
|
||||
let count = 0;
|
||||
const perfectPlan = (node1, node2, target1, target2, value = 0, targeted = {"AA": true}, time = 26) => {
|
||||
if(time < 1) {
|
||||
return;
|
||||
}
|
||||
count++;
|
||||
if(!(count % 2000000)) {
|
||||
console.log("Evaluated ", count, "possible minutes");
|
||||
}
|
||||
let acted1 = false;
|
||||
let acted2 = false;
|
||||
if(target1 === node1) {
|
||||
target1 = undefined;
|
||||
acted1 = true;
|
||||
value = value + (time - 1) * node1.rate;
|
||||
}
|
||||
|
||||
if(target2 === node2) {
|
||||
target2 = undefined;
|
||||
acted2 = true;
|
||||
value = value + (time - 1) * node2.rate;
|
||||
}
|
||||
|
||||
if(value > best) {
|
||||
best = value;
|
||||
console.log(`${best} is better!`);
|
||||
}
|
||||
if(!bestPerTime[time] || bestPerTime[time] <= value) {
|
||||
bestPerTime[time] = value;
|
||||
}
|
||||
//1.5 seems to work. Higher values work faster, but risk missing the best path
|
||||
const lowBar = bestPerTime[Math.floor(time + time/1.5)];
|
||||
if(lowBar && lowBar > value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const paths1 = valvePaths[node1.id];
|
||||
const paths2 = valvePaths[node2.id];
|
||||
|
||||
const possibleNodes = nodesByRate.filter(n => !targeted[n.id]);
|
||||
|
||||
for(const next1 of possibleNodes) {
|
||||
for(const next2 of possibleNodes) {
|
||||
if(next1 === next2) {
|
||||
continue;
|
||||
}
|
||||
const n1 = acted1 ? node1 : target1 ? paths1[target1.id][0] : paths1[next1.id][0];
|
||||
const n2 = acted2 ? node2 : target2 ? paths2[target2.id][0] : paths2[next2.id][0];
|
||||
const t1 = acted1 ? null : target1 || next1;
|
||||
const t2 = acted2 ? null : target2 || next2;
|
||||
if(t2 && t1 && paths1[t2.id].length < paths2[t2.id].length && paths2[t1.id].length < paths2[t2.id].length) {
|
||||
continue;
|
||||
}
|
||||
const newTargeted = {...targeted};
|
||||
if(t1) {
|
||||
newTargeted[t1.id] = true;
|
||||
}
|
||||
if(t2) {
|
||||
newTargeted[t2.id] = true;
|
||||
}
|
||||
perfectPlan(n1, n2, t1, t2, value, {...newTargeted}, time - 1);
|
||||
if(target2 || acted2) break;
|
||||
}
|
||||
if(target1 || acted1) break;
|
||||
}
|
||||
};
|
||||
|
||||
perfectPlan(nodesById["AA"], nodesById["AA"]);
|
||||
console.log("Answer is: ", best);
|
||||
}
|
||||
|
||||
main();
|
60
2022/16/input.txt
Normal file
60
2022/16/input.txt
Normal file
|
@ -0,0 +1,60 @@
|
|||
Valve QP has flow rate=0; tunnels lead to valves IS, DG
|
||||
Valve MC has flow rate=0; tunnels lead to valves XX, QQ
|
||||
Valve OT has flow rate=7; tunnels lead to valves OE, BL, DJ, JS, LS
|
||||
Valve CZ has flow rate=0; tunnels lead to valves IC, ZL
|
||||
Valve GI has flow rate=0; tunnels lead to valves OM, GF
|
||||
Valve YB has flow rate=0; tunnels lead to valves DQ, MX
|
||||
Valve EJ has flow rate=0; tunnels lead to valves GB, ES
|
||||
Valve IS has flow rate=19; tunnels lead to valves AS, OB, QP
|
||||
Valve WI has flow rate=21; tunnels lead to valves SS, AK
|
||||
Valve JS has flow rate=0; tunnels lead to valves OT, HV
|
||||
Valve UR has flow rate=0; tunnels lead to valves OM, ZI
|
||||
Valve UC has flow rate=0; tunnels lead to valves QX, NG
|
||||
Valve BL has flow rate=0; tunnels lead to valves YW, OT
|
||||
Valve AK has flow rate=0; tunnels lead to valves WI, AL
|
||||
Valve QQ has flow rate=16; tunnels lead to valves MC, WH, MS, IY
|
||||
Valve PW has flow rate=0; tunnels lead to valves ZL, EK
|
||||
Valve AS has flow rate=0; tunnels lead to valves IS, MS
|
||||
Valve ZL has flow rate=9; tunnels lead to valves CD, QX, PW, CZ, PQ
|
||||
Valve OB has flow rate=0; tunnels lead to valves HS, IS
|
||||
Valve OE has flow rate=0; tunnels lead to valves IC, OT
|
||||
Valve AL has flow rate=0; tunnels lead to valves VX, AK
|
||||
Valve AM has flow rate=0; tunnels lead to valves OM, YW
|
||||
Valve QX has flow rate=0; tunnels lead to valves UC, ZL
|
||||
Valve DJ has flow rate=0; tunnels lead to valves OT, ST
|
||||
Valve ZI has flow rate=0; tunnels lead to valves VX, UR
|
||||
Valve PQ has flow rate=0; tunnels lead to valves ZL, YW
|
||||
Valve OM has flow rate=22; tunnels lead to valves GI, AM, EK, UR
|
||||
Valve NG has flow rate=13; tunnels lead to valves UC, HS, GF
|
||||
Valve AA has flow rate=0; tunnels lead to valves UJ, ES, JP, HY, ST
|
||||
Valve HY has flow rate=0; tunnels lead to valves GZ, AA
|
||||
Valve MS has flow rate=0; tunnels lead to valves AS, QQ
|
||||
Valve JK has flow rate=0; tunnels lead to valves YW, GB
|
||||
Valve JP has flow rate=0; tunnels lead to valves AA, PF
|
||||
Valve ST has flow rate=0; tunnels lead to valves AA, DJ
|
||||
Valve CD has flow rate=0; tunnels lead to valves SS, ZL
|
||||
Valve ES has flow rate=0; tunnels lead to valves EJ, AA
|
||||
Valve PF has flow rate=0; tunnels lead to valves JP, HV
|
||||
Valve RL has flow rate=0; tunnels lead to valves GB, IC
|
||||
Valve IY has flow rate=0; tunnels lead to valves QQ, SN
|
||||
Valve UJ has flow rate=0; tunnels lead to valves IC, AA
|
||||
Valve HS has flow rate=0; tunnels lead to valves NG, OB
|
||||
Valve WH has flow rate=0; tunnels lead to valves QQ, MX
|
||||
Valve YA has flow rate=0; tunnels lead to valves GB, HV
|
||||
Valve SN has flow rate=0; tunnels lead to valves IY, DG
|
||||
Valve GF has flow rate=0; tunnels lead to valves GI, NG
|
||||
Valve YW has flow rate=8; tunnels lead to valves GZ, JK, BL, PQ, AM
|
||||
Valve DG has flow rate=17; tunnels lead to valves QP, SN
|
||||
Valve MX has flow rate=11; tunnels lead to valves WH, YB
|
||||
Valve DQ has flow rate=0; tunnels lead to valves YB, HV
|
||||
Valve SS has flow rate=0; tunnels lead to valves CD, WI
|
||||
Valve HV has flow rate=4; tunnels lead to valves YA, DQ, TO, JS, PF
|
||||
Valve GB has flow rate=6; tunnels lead to valves LS, RL, JK, EJ, YA
|
||||
Valve EK has flow rate=0; tunnels lead to valves OM, PW
|
||||
Valve LS has flow rate=0; tunnels lead to valves GB, OT
|
||||
Valve IC has flow rate=5; tunnels lead to valves CZ, OE, UJ, TO, RL
|
||||
Valve XX has flow rate=0; tunnels lead to valves MC, FM
|
||||
Valve VX has flow rate=25; tunnels lead to valves ZI, AL
|
||||
Valve GZ has flow rate=0; tunnels lead to valves HY, YW
|
||||
Valve FM has flow rate=20; tunnel leads to valve XX
|
||||
Valve TO has flow rate=0; tunnels lead to valves IC, HV
|
Loading…
Reference in a new issue