From 95754d7b78b774b6312736eb82588485b0a1f025 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 30 Nov 2023 10:13:16 -0500 Subject: [PATCH] prettier --- 2022/15/part1.js | 115 +++++++++++++++++----------------- 2022/15/part2.js | 80 ++++++++++-------------- 2022/15/test.js | 32 +++++----- 2022/16/part1.js | 120 +++++++++++++++++++----------------- 2022/16/part2.js | 157 ++++++++++++++++++++++++++--------------------- 2022/16/test.js | 21 +++---- 6 files changed, 264 insertions(+), 261 deletions(-) diff --git a/2022/15/part1.js b/2022/15/part1.js index a196927..88f25f5 100644 --- a/2022/15/part1.js +++ b/2022/15/part1.js @@ -3,81 +3,76 @@ import * as R from "remeda"; import { passthru } from "../08/part1.js"; import { readFile } from "../05/part1.js"; -import V from '@yanick/vyktor'; +import V from "@yanick/vyktor"; import { createLogger } from "vite"; const readInput = (...args) => - R.pipe( - readFile(...args), - (lines) => lines.split("\n"), - R.compact, // remove last line - R.map(line => line.match(/x=-?.*?y=-?\d+/g).map(str => - str.match(/-?\d+/g).map(x => parseInt(x))).map( - coords => V(coords) - ) - )); + R.pipe( + readFile(...args), + (lines) => lines.split("\n"), + R.compact, // remove last line + R.map((line) => + line + .match(/x=-?.*?y=-?\d+/g) + .map((str) => str.match(/-?\d+/g).map((x) => parseInt(x))) + .map((coords) => V(coords)) + ) + ); export const puzzleInput = readInput(import.meta.url, "input"); export const sample = readInput(import.meta.url, "sample"); /** @returns [number,number][] */ -export const mergeRanges = ( ranges ) => { - -return ranges.reduce( (accum,range) => { - if( accum.length === 0 ) return [ range ]; - if( R.last( accum )[1] < range[0] ) { - accum.push(range); - } - else { - R.last(accum)[1] = Math.max( - R.last(accum)[1], range[1] - ) - } - return accum; - }, [] ); -} - -export const spy = passthru( x => console.log(x) ); - -const entriesInRange = (targetLine,entries) => { - - entries = R.uniqBy(entries.map(([_,beacon])=>beacon).filter( beacon => beacon?.y === targetLine ), (x) => x.toString()); - - return range => { - return entries.filter( - entry => (entry.x >= range[0]) && (entry.x <= range[1]) - ).length +export const mergeRanges = (ranges) => { + return ranges.reduce((accum, range) => { + if (accum.length === 0) return [range]; + if (R.last(accum)[1] < range[0]) { + accum.push(range); + } else { + R.last(accum)[1] = Math.max(R.last(accum)[1], range[1]); } + return accum; + }, []); }; -export const unbeaconAtLine = targetLine => entries => R.pipe( - entries, - R.map( ([x,y]) => [ x, x.manhattanDistance(y) ] ), - R.filter( -e => ( - ( e[0].y - e[1] <= targetLine) && - ( e[0].y + e[1] >= targetLine) - ) - ), - R.map( - e => { - const l = e[1] - Math.abs(targetLine - e[0].y); +export const spy = passthru((x) => console.log(x)); - return [ - e[0].x - l, - e[0].x + l ] - } - ), +const entriesInRange = (targetLine, entries) => { + entries = R.uniqBy( + entries + .map(([_, beacon]) => beacon) + .filter((beacon) => beacon?.y === targetLine), + (x) => x.toString() + ); + + return (range) => { + return entries.filter((entry) => entry.x >= range[0] && entry.x <= range[1]) + .length; + }; +}; + +export const unbeaconAtLine = (targetLine) => (entries) => + R.pipe( + entries, + R.map(([x, y]) => [x, x.manhattanDistance(y)]), + R.filter((e) => e[0].y - e[1] <= targetLine && e[0].y + e[1] >= targetLine), + R.map((e) => { + const l = e[1] - Math.abs(targetLine - e[0].y); + + return [e[0].x - l, e[0].x + l]; + }), spy, - (ranges) => - ranges.sort( (a,b) => { - return (a[0] - b[0]) || (a[1]-b[1]); - } ) - , + (ranges) => + ranges.sort((a, b) => { + return a[0] - b[0] || a[1] - b[1]; + }), spy, mergeRanges, spy, - R.sumBy( range => range[1] - range[0] + 1 - entriesInRange(targetLine,entries)(range) ) - ); + R.sumBy( + (range) => + range[1] - range[0] + 1 - entriesInRange(targetLine, entries)(range) + ) + ); export default unbeaconAtLine(2000000); diff --git a/2022/15/part2.js b/2022/15/part2.js index 543b6bf..1aa3362 100644 --- a/2022/15/part2.js +++ b/2022/15/part2.js @@ -1,63 +1,47 @@ import * as R from "remeda"; -import V from '@yanick/vyktor'; +import V from "@yanick/vyktor"; -import { - spy, -mergeRanges -} from './part1.js'; +import { spy, mergeRanges } from "./part1.js"; -const unbeaconAtLine = (max,targetLine,already) => entries => R.pipe( +const unbeaconAtLine = (max, targetLine, already) => (entries) => + R.pipe( entries, - R.map( ([x,y]) => [ x, x.manhattanDistance(y) ] ), - R.filter( -e => ( - ( e[0].y - e[1] <= targetLine) && - ( e[0].y + e[1] >= targetLine) - ) - ), - R.map( - e => { - const l = e[1] - Math.abs(targetLine - e[0].y); + R.map(([x, y]) => [x, x.manhattanDistance(y)]), + R.filter((e) => e[0].y - e[1] <= targetLine && e[0].y + e[1] >= targetLine), + R.map((e) => { + const l = e[1] - Math.abs(targetLine - e[0].y); - return [ - e[0].x - l, - e[0].x + l ] - } - ), + return [e[0].x - l, e[0].x + l]; + }), //spy, (ranges) => [ - ...ranges, ...already.filter( v => v.y === targetLine ).map( - v => [ v.x,v.x ] - ) + ...ranges, + ...already.filter((v) => v.y === targetLine).map((v) => [v.x, v.x]), ], - (ranges) => - ranges.sort( (a,b) => { - return (a[0] - b[0]) || (a[1]-b[1]); - } ) - , + (ranges) => + ranges.sort((a, b) => { + return a[0] - b[0] || a[1] - b[1]; + }), // spy, - R.map( - range => [ Math.max(0,range[0]), Math.min(max,range[1])] - ), - mergeRanges, + R.map((range) => [Math.max(0, range[0]), Math.min(max, range[1])]), + mergeRanges // spy, - // R.sumBy( range => range[1] - range[0] + 1 - entriesInRange(targetLine,entries)(range) ) - ); + // R.sumBy( range => range[1] - range[0] + 1 - entriesInRange(targetLine,entries)(range) ) + ); -export const findBeacon = max => entries => { +export const findBeacon = (max) => (entries) => { + const already = entries.flat(); - const already = entries.flat() - - for (let y = 0; y <= max; y++) { - const ranges = unbeaconAtLine(max,y,already)(entries) - if( ranges.length > 1 ) { - return y + 4000000 * (ranges[0][1] +1); - } - -// return 'bob'; - - // return x * 4000000 + y; + for (let y = 0; y <= max; y++) { + const ranges = unbeaconAtLine(max, y, already)(entries); + if (ranges.length > 1) { + return y + 4000000 * (ranges[0][1] + 1); } -} + + // return 'bob'; + + // return x * 4000000 + y; + } +}; export default findBeacon(4000000); diff --git a/2022/15/test.js b/2022/15/test.js index e53af8b..6a64baa 100644 --- a/2022/15/test.js +++ b/2022/15/test.js @@ -5,25 +5,25 @@ import part1, { sample, puzzleInput, unbeaconAtLine } from "./part1.js"; import part2, { findBeacon } from "./part2.js"; describe("part 1", () => { - test('readInput', () => { - expect(sample[0][0].toArray()).toEqual([2, 18]); - }); + test("readInput", () => { + expect(sample[0][0].toArray()).toEqual([2, 18]); + }); - test('sample', () => { - expect(unbeaconAtLine(10)(sample)).toEqual(26); - }); + test("sample", () => { + expect(unbeaconAtLine(10)(sample)).toEqual(26); + }); - test("solution", () => { - expectSolution(part1(puzzleInput)).toEqual(5525990); - }); + test("solution", () => { + expectSolution(part1(puzzleInput)).toEqual(5525990); + }); }); describe("part 2", () => { - test('sample', () => { - expect(findBeacon(20)(sample)).toEqual(56000011); - }); - test("solution", () => { - // 314 seconds! - expectSolution(part2(puzzleInput)).toEqual(11756174628223); - }); + test("sample", () => { + expect(findBeacon(20)(sample)).toEqual(56000011); + }); + test("solution", () => { + // 314 seconds! + expectSolution(part2(puzzleInput)).toEqual(11756174628223); + }); }); diff --git a/2022/16/part1.js b/2022/16/part1.js index 859c0be..20f0416 100644 --- a/2022/16/part1.js +++ b/2022/16/part1.js @@ -1,92 +1,98 @@ import * as R from "remeda"; import u from "updeep"; -import Graph from 'graphology'; -import { bidirectional } from 'graphology-shortest-path'; +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 { 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, - ); + 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); +function finalSteam( + tunnels, + graph, + minutesLeft, + possibilities, + location = "AA", + activeSteam = 0 +) { + //console.log(minutesLeft, totalSteam, itinary); - if (minutesLeft <= 0) return 0; + if (minutesLeft <= 0) return 0; - if (possibilities.length === 0) return minutesLeft * activeSteam; + if (possibilities.length === 0) return minutesLeft * activeSteam; - let scores = []; + let scores = []; + + for (const next of possibilities) { + const path = bidirectional(graph, location, next); - 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(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 - ) - ) + scores.push( + ts + + finalSteam( + tunnels, + graph, + minutesLeft - time, + possibilities.filter((x) => x !== next), + next, + as + ) + ); } + } - } - - return Math.max( ...scores ); + return Math.max(...scores); } -export const buildGraph = tunnels => { - const graph = new Graph(); - Object.keys(tunnels).forEach(x => graph.addNode(x)); +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; + 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 possibilities = - Object.keys(tunnels).filter( - k => tunnels[k].flow - ); - - const graph = buildGraph(tunnels); - - return finalSteam(tunnels, graph, 30, possibilities, 'AA', 0, 0) + const graph = buildGraph(tunnels); + return finalSteam(tunnels, graph, 30, possibilities, "AA", 0, 0); }; diff --git a/2022/16/part2.js b/2022/16/part2.js index 1c649cb..c9cd5b7 100644 --- a/2022/16/part2.js +++ b/2022/16/part2.js @@ -1,86 +1,105 @@ -import { bidirectional } from 'graphology-shortest-path'; +import { bidirectional } from "graphology-shortest-path"; import * as R from "remeda"; -import u from 'updeep'; +import u from "updeep"; -import { buildGraph } from './part1.js'; +import { buildGraph } from "./part1.js"; -const findMaxSteam = (tunnels,graph, minutesLeft, unopened, opened, activeSteam, peeps ) => { +const findMaxSteam = ( + tunnels, + graph, + minutesLeft, + unopened, + opened, + activeSteam, + peeps +) => { + console.log({ unopened, activeSteam, minutesLeft }); - console.log({ unopened, activeSteam, minutesLeft}); + let next = R.sortBy(peeps, R.prop("eta")); - let next = R.sortBy(peeps, R.prop('eta')); + if (next[0].eta > minutesLeft) { + return minutesLeft * activeSteam; + } - if( next[0].eta > minutesLeft ) { - return minutesLeft * activeSteam; + const delta = next[0].eta; + const location = next[0].destination; + + const base = delta * activeSteam; + minutesLeft -= delta; + + activeSteam += tunnels[next[0].destination].flow; + opened = [...opened, next[0].destination]; + + next = u.updateIn("1.eta", (eta) => eta - delta, next); + + const scores = []; + + let nothing = true; + for (const destination of unopened) { + const path = bidirectional(graph, location, destination); + + if (path.length > minutesLeft) { + continue; } + nothing = false; - const delta = next[0].eta; - const location = next[0].destination; + next = u.updateIn( + "0", + { + location, + eta: path.length, + destination, + }, + next + ); - const base = delta * activeSteam; - minutesLeft -= delta; + scores.push( + findMaxSteam( + tunnels, + graph, + minutesLeft, + unopened.filter((x) => x !== destination), + opened, + activeSteam, + next + ) + ); + } - activeSteam += tunnels[ next[0].destination ].flow; - opened = [ ...opened, next[0].destination ]; + if (nothing) { + next = u.updateIn( + "0", + { + location, + eta: 999, + destination: "END", + }, + next + ); - next = u.updateIn( '1.eta', eta => eta - delta, next ); + scores.push( + findMaxSteam( + tunnels, + graph, + minutesLeft, + unopened, + opened, + activeSteam, + next + ) + ); + } - const scores = []; - - - - - let nothing = true; - for ( const destination of unopened ) { - const path = bidirectional(graph, location, destination ); - - if( path.length > minutesLeft) { - continue; - } - nothing = false; - - next = u.updateIn( '0', { - location, - eta: path.length, - destination - },next); - - scores.push( findMaxSteam(tunnels,graph,minutesLeft, - unopened.filter( x => x !== destination ), - opened, activeSteam, next - ) ); - } - - if( nothing ) { - next = u.updateIn( '0', { - location, - eta: 999, - destination: 'END', - },next); - - scores.push( findMaxSteam(tunnels,graph,minutesLeft, - unopened, - opened, activeSteam, next - ) ); - } - - return base + Math.max( ...scores ); - - -} + return base + Math.max(...scores); +}; export default (tunnels) => { + const possibilities = Object.keys(tunnels).filter((k) => tunnels[k].flow); - const possibilities = - Object.keys(tunnels).filter( - k => tunnels[k].flow - ); - - const graph = buildGraph(tunnels); - - return findMaxSteam(tunnels, graph, 26, possibilities,[],0, [ - { destination: 'AA', eta: 0 }, - { destination: 'AA', eta: 0 }, - ]) + const graph = buildGraph(tunnels); + return findMaxSteam(tunnels, graph, 26, possibilities, [], 0, [ + { destination: "AA", eta: 0 }, + { destination: "AA", eta: 0 }, + ]); }; diff --git a/2022/16/test.js b/2022/16/test.js index 44c122e..a6942a5 100644 --- a/2022/16/test.js +++ b/2022/16/test.js @@ -5,21 +5,20 @@ import part1, { sample, puzzleInput } from "./part1.js"; import part2 from "./part2.js"; describe("part 1", () => { - test( "input", ()=> { - expect(sample).toMatchObject({AA: { - exists: [ - 'DD', 'II', 'BB', - ], - flow: 0, - }}) - - } ) + test("input", () => { + expect(sample).toMatchObject({ + AA: { + exists: ["DD", "II", "BB"], + flow: 0, + }, + }); + }); test("sample", () => { expect(part1(sample)).toEqual(1651); }); test("solution", () => { - const r= part1(puzzleInput); - expect(r).toBeGreaterThan(707); + const r = part1(puzzleInput); + expect(r).toBeGreaterThan(707); expectSolution(part1(puzzleInput)).toEqual(1871); }); });