part 2, wip
This commit is contained in:
parent
bc6b5259c1
commit
1a855600cf
106
2022/16/part1.js
106
2022/16/part1.js
@ -2,77 +2,91 @@ import * as R from "remeda";
|
|||||||
import u from "updeep";
|
import u from "updeep";
|
||||||
|
|
||||||
import Graph from 'graphology';
|
import Graph from 'graphology';
|
||||||
import {bidirectional} from 'graphology-shortest-path';
|
import { bidirectional } from 'graphology-shortest-path';
|
||||||
|
|
||||||
import { combinations } from "combinatorial-generators";
|
import { combinations, permutations } from "combinatorial-generators";
|
||||||
|
|
||||||
import { readFile } from "../05/part1.js";
|
import { readFile } from "../05/part1.js";
|
||||||
|
|
||||||
const parseLine = (line) => {
|
const parseLine = (line) => {
|
||||||
const {groups} = line.match( /Valve (?<valve>..).*flow rate=(?<flow>\d+).*valves? (?<exits>.*)/ );
|
const { groups } = line.match(/Valve (?<valve>..).*flow rate=(?<flow>\d+).*valves? (?<exits>.*)/);
|
||||||
return [ groups.valve, {
|
return [groups.valve, {
|
||||||
exits: groups.exits.split(',').map( x => x.trim() ),
|
exits: groups.exits.split(',').map(x => x.trim()),
|
||||||
flow: groups.flow
|
flow: parseInt(groups.flow)
|
||||||
} ]
|
}]
|
||||||
}
|
}
|
||||||
const readInput = (...args) =>
|
const readInput = (...args) =>
|
||||||
R.pipe(
|
R.pipe(
|
||||||
readFile(...args),
|
readFile(...args),
|
||||||
(lines) => lines.split("\n"),
|
(lines) => lines.split("\n"),
|
||||||
R.compact, // remove last line
|
R.compact, // remove last line
|
||||||
R.map(parseLine),
|
R.map(parseLine),
|
||||||
Object.fromEntries,
|
Object.fromEntries,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const puzzleInput = readInput(import.meta.url, "input");
|
export const puzzleInput = readInput(import.meta.url, "input");
|
||||||
export const sample = readInput(import.meta.url, "sample");
|
export const sample = readInput(import.meta.url, "sample");
|
||||||
|
|
||||||
function bestMoveFor(tunnels,minutesLeft,opened,location='AA',totalSteam=0,activeSteam=0) {
|
function finalSteam(tunnels, graph, minutesLeft, possibilities, location = 'AA', activeSteam = 0) {
|
||||||
console.log(minutesLeft, totalSteam);
|
//console.log(minutesLeft, totalSteam, itinary);
|
||||||
|
|
||||||
if(minutesLeft<=0) return totalSteam;
|
if (minutesLeft <= 0) return 0;
|
||||||
|
|
||||||
totalSteam += activeSteam;
|
if (possibilities.length === 0) return minutesLeft * activeSteam;
|
||||||
|
|
||||||
const possibilities = [];
|
let scores = [];
|
||||||
|
|
||||||
if(!opened.includes(location)) {
|
for ( const next of possibilities ) {
|
||||||
possibilities.push(
|
const path = bidirectional(graph, location, next);
|
||||||
bestMoveFor(
|
|
||||||
tunnels,
|
//console.log(path);
|
||||||
minutesLeft-1,
|
|
||||||
[...opened, location],
|
let time = path.length;
|
||||||
location,
|
if (time >= minutesLeft) {
|
||||||
totalSteam,
|
scores.push( minutesLeft * activeSteam );
|
||||||
activeSteam + tunnels[location].flow
|
}
|
||||||
)
|
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
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for( const exit of tunnels[location].exits ) {
|
|
||||||
possibilities.push(
|
|
||||||
bestMoveFor(
|
|
||||||
tunnels,
|
|
||||||
minutesLeft-1,
|
|
||||||
opened,
|
|
||||||
exit,
|
|
||||||
totalSteam,
|
|
||||||
activeSteam,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.max( ...possibilities );
|
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) => {
|
export default (tunnels) => {
|
||||||
|
|
||||||
const graph = new Graph();
|
const possibilities =
|
||||||
Object.entries(tunnels).forEach( ([location, { exits }]) => {
|
Object.keys(tunnels).filter(
|
||||||
exits.forEach( exit => graph.addEdge(location, exit) );
|
k => tunnels[k].flow
|
||||||
});
|
);
|
||||||
|
|
||||||
console.log(graph);
|
const graph = buildGraph(tunnels);
|
||||||
|
|
||||||
|
return finalSteam(tunnels, graph, 30, possibilities, 'AA', 0, 0)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,72 @@
|
|||||||
|
import { bidirectional } from 'graphology-shortest-path';
|
||||||
import * as R from "remeda";
|
import * as R from "remeda";
|
||||||
|
|
||||||
|
import { buildGraph } from './part1.js';
|
||||||
|
|
||||||
export default () => {};
|
function finalSteam(tunnels, graph, minutesLeft, possibilities, locations, activeSteam = 0) {
|
||||||
|
//console.log(minutesLeft, activeSteam, locations, possibilities);
|
||||||
|
|
||||||
|
if (minutesLeft <= 0) return 0;
|
||||||
|
|
||||||
|
if (possibilities.length === 0) return minutesLeft * activeSteam;
|
||||||
|
|
||||||
|
const nextToGo = locations.find(([time]) => !time);
|
||||||
|
|
||||||
|
for( const l of locations) {
|
||||||
|
if( l[0] === 0 ) {
|
||||||
|
activeSteam += l[2];
|
||||||
|
l[2] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let scores = [];
|
||||||
|
|
||||||
|
for ( const next of possibilities ) {
|
||||||
|
const path = bidirectional(graph, nextToGo[1], next);
|
||||||
|
|
||||||
|
//console.log(path);
|
||||||
|
|
||||||
|
const locs = locations.map( x => x === nextToGo ? [
|
||||||
|
path.length, next, tunnels[next].flow
|
||||||
|
] : x );
|
||||||
|
|
||||||
|
let time = Math.min( ...locs.map( ([time]) => time ) );
|
||||||
|
|
||||||
|
if (time >= minutesLeft) {
|
||||||
|
scores.push( minutesLeft * activeSteam );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//console.log({totalSteam, time, activeSteam});
|
||||||
|
let ts = time * activeSteam;
|
||||||
|
|
||||||
|
scores.push(
|
||||||
|
ts + finalSteam(
|
||||||
|
tunnels, graph, minutesLeft - time,
|
||||||
|
possibilities.filter( x => x !== next ),
|
||||||
|
locs.map( ([t,dest] ) => [ t -time, dest ]),
|
||||||
|
activeSteam
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max( ...scores );
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (tunnels) => {
|
||||||
|
|
||||||
|
const possibilities =
|
||||||
|
Object.keys(tunnels).filter(
|
||||||
|
k => tunnels[k].flow
|
||||||
|
);
|
||||||
|
|
||||||
|
const graph = buildGraph(tunnels);
|
||||||
|
|
||||||
|
return finalSteam(tunnels, graph, 26, possibilities, [
|
||||||
|
[ 0, 'AA' ],
|
||||||
|
[ 0, 'AA' ]
|
||||||
|
], 0, 0)
|
||||||
|
|
||||||
|
};
|
||||||
|
@ -14,15 +14,20 @@ describe("part 1", () => {
|
|||||||
}})
|
}})
|
||||||
|
|
||||||
} )
|
} )
|
||||||
test.only("sample", () => {
|
test("sample", () => {
|
||||||
expectSolution(part1(sample)).toEqual(1651);
|
expect(part1(sample)).toEqual(1651);
|
||||||
});
|
});
|
||||||
test.todo("solution", () => {
|
test.only("solution", () => {
|
||||||
expectSolution(part1(puzzleInput)).toEqual("TODO");
|
const r= part1(puzzleInput);
|
||||||
|
expect(r).toBeGreaterThan(707);
|
||||||
|
expectSolution(part1(puzzleInput)).toEqual(1871);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("part 2", () => {
|
describe.only("part 2", () => {
|
||||||
|
test("sample", () => {
|
||||||
|
expect(part2(sample)).toEqual(1707);
|
||||||
|
});
|
||||||
test.todo("solution", () => {
|
test.todo("solution", () => {
|
||||||
expectSolution(part2(puzzleInput)).toEqual("TODO");
|
expectSolution(part2(puzzleInput)).toEqual("TODO");
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user