From 80800918705bbb5cbe9e69349b9c46c2e0bb68ae Mon Sep 17 00:00:00 2001 From: John Shaver Date: Sat, 17 Dec 2022 16:17:24 -0800 Subject: [PATCH] 16.1 and 16.2 --- 2022/16/example.txt | 14 +++++ 2022/16/index.js | 87 ++++++++++++++++++++++++++++ 2022/16/index2.js | 135 ++++++++++++++++++++++++++++++++++++++++++++ 2022/16/input.txt | 60 ++++++++++++++++++++ 4 files changed, 296 insertions(+) create mode 100644 2022/16/example.txt create mode 100644 2022/16/index.js create mode 100644 2022/16/index2.js create mode 100644 2022/16/input.txt diff --git a/2022/16/example.txt b/2022/16/example.txt new file mode 100644 index 0000000..a612424 --- /dev/null +++ b/2022/16/example.txt @@ -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 diff --git a/2022/16/index.js b/2022/16/index.js new file mode 100644 index 0000000..bbdf452 --- /dev/null +++ b/2022/16/index.js @@ -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(); diff --git a/2022/16/index2.js b/2022/16/index2.js new file mode 100644 index 0000000..e0999cd --- /dev/null +++ b/2022/16/index2.js @@ -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(); diff --git a/2022/16/input.txt b/2022/16/input.txt new file mode 100644 index 0000000..77f6bb1 --- /dev/null +++ b/2022/16/input.txt @@ -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