From 57a4e799a895935b0fbb5eea8653e43eefd49975 Mon Sep 17 00:00:00 2001 From: Seth Etter Date: Tue, 5 Dec 2023 22:03:57 -0600 Subject: [PATCH] use workers! --- 2023/day05/part2-worker.ts | 38 +++++++++++++++++++++++++++++++++ 2023/day05/part2.ts | 43 ++++++++++++++++++++++++++------------ 2 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 2023/day05/part2-worker.ts diff --git a/2023/day05/part2-worker.ts b/2023/day05/part2-worker.ts new file mode 100644 index 0000000..0c6e6da --- /dev/null +++ b/2023/day05/part2-worker.ts @@ -0,0 +1,38 @@ +import { assert } from "https://deno.land/std@0.208.0/assert/mod.ts"; +import { MapRanges } from "./part2.ts"; + +type MessageData = { + range: [number, number]; + mapRanges: MapRanges[]; +}; + +self.onmessage = ({ data: { range, mapRanges } }: { data: MessageData }) => { + const [from, to] = range; + console.log(`(start) worker ${from}-${to}`); + let minLocNum = Infinity; + for (let j = 0; j < to - from; j++) { + const seed = from + j; + const locNum = getLocationNumber(seed, mapRanges); + if (locNum < minLocNum) minLocNum = locNum; + } + self.postMessage({ minLocNum }); + console.log(`(end) worker ${from}-${to}: ${minLocNum}`); + self.close(); +}; + +function getLocationNumber(seed: number, mapRanges: MapRanges[]): number { + let current = "seed"; + let currentNum = seed; + while (current !== "location") { + const mapRange = mapRanges.find(({ from }) => from === current); + assert(mapRange, `mapRange not found for: ${current}`); + + const range = mapRange.ranges.find( + (r) => currentNum >= r.fromStart && currentNum <= r.fromStart + r.range, + ); + if (range) currentNum = currentNum + (range.toStart - range.fromStart); + + current = mapRange.to; + } + return currentNum; +} diff --git a/2023/day05/part2.ts b/2023/day05/part2.ts index 1975b49..2818e45 100644 --- a/2023/day05/part2.ts +++ b/2023/day05/part2.ts @@ -9,13 +9,13 @@ if (import.meta.main) { console.log(await answer(input)); } -type Range = { +export type Range = { fromStart: number; toStart: number; range: number; }; -type MapRanges = { +export type MapRanges = { from: string; to: string; ranges: Range[]; @@ -50,17 +50,24 @@ export async function answer(input: string): Promise { const to = from + seedRangeLines[i + 1]; seedRanges.push([from, to]); } - const rangeMins = await Promise.all( - seedRanges.map( - ([from, to]) => - new Promise((resolve) => { - let minLocNum = Infinity; - for (let j = 0; j < to - from; j++) { - const seed = from + j; - const locNum = getLocationNumber(seed, mapRanges); - if (locNum < minLocNum) minLocNum = locNum; - } - return resolve(minLocNum); + + const rangeMins: number[] = await Promise.all( + splitRanges(seedRanges).map( + (range) => + new Promise((resolve, reject) => { + const worker = new Worker( + new URL("./part2-worker.ts", import.meta.url).href, + { + type: "module", + }, + ); + worker.postMessage({ range, mapRanges }); + worker.onmessage = ({ data }) => { + if (typeof data?.minLocNum !== "number") { + return reject(new Error(`invalid message: ${data}`)); + } + return resolve(data.minLocNum); + }; }), ), ); @@ -68,6 +75,16 @@ export async function answer(input: string): Promise { return Math.min(...rangeMins); } +function splitRanges(ranges: [number, number][]): [number, number][] { + const newRanges: [number, number][] = []; + for (const [from, to] of ranges) { + const middle = Math.ceil(from + (to - from) / 2); + newRanges.push([from, middle]); + newRanges.push([middle + 1, to]); + } + return newRanges; +} + function getLocationNumber(seed: number, mapRanges: MapRanges[]): number { let current = "seed"; let currentNum = seed; -- 2.51.2