import * as R from "remeda"; import u from "updeep"; import Graph from "graphology"; import { bidirectional } from "graphology-shortest-path"; import { combinations, permutations } from "combinatorial-generators"; import { readFile } from "../05/part1.js"; const parseLine = (line) => { const { groups } = line.match( /Valve (?..).*flow rate=(?\d+).*valves? (?.*)/ ); return [ groups.valve, { exits: groups.exits.split(",").map((x) => x.trim()), flow: parseInt(groups.flow), }, ]; }; const readInput = (...args) => R.pipe( readFile(...args), (lines) => lines.split("\n"), R.compact, // remove last line R.map(parseLine), Object.fromEntries ); export const puzzleInput = readInput(import.meta.url, "input"); export const sample = readInput(import.meta.url, "sample"); function finalSteam( tunnels, graph, minutesLeft, possibilities, location = "AA", activeSteam = 0 ) { //console.log(minutesLeft, totalSteam, itinary); if (minutesLeft <= 0) return 0; if (possibilities.length === 0) return minutesLeft * activeSteam; let scores = []; for (const next of possibilities) { const path = bidirectional(graph, location, next); //console.log(path); let time = path.length; if (time >= minutesLeft) { scores.push(minutesLeft * activeSteam); } else { //console.log({totalSteam, time, activeSteam}); let ts = time * activeSteam; let as = activeSteam + tunnels[next].flow; scores.push( ts + finalSteam( tunnels, graph, minutesLeft - time, possibilities.filter((x) => x !== next), next, as ) ); } } return Math.max(...scores); } export const buildGraph = (tunnels) => { const graph = new Graph(); Object.keys(tunnels).forEach((x) => graph.addNode(x)); Object.entries(tunnels).forEach(([location, { exits }]) => { exits.forEach((exit) => graph.addEdge(location, exit)); }); return graph; }; export default (tunnels) => { const possibilities = Object.keys(tunnels).filter((k) => tunnels[k].flow); const graph = buildGraph(tunnels); return finalSteam(tunnels, graph, 30, possibilities, "AA", 0, 0); };