diff --git a/2024/day-11/blink-worker.ts b/2024/day-11/blink-worker.ts new file mode 100644 index 0000000..de69133 --- /dev/null +++ b/2024/day-11/blink-worker.ts @@ -0,0 +1,40 @@ +import { parentPort, workerData } from "node:worker_threads"; + +const cache = new Map>(); + +function transformSingleStone(stone: number): number[] { + if (cache.has(stone)) { + // biome-ignore lint/style/noNonNullAssertion: it's there, I promise + return cache.get(stone)!; + } + if (stone === 0) { + cache.set(stone, [1]); + return [1]; + } + const numberAsString = stone.toString(); + const numberOfDigits = numberAsString.length; + if (numberOfDigits % 2 === 0) { + const middle = numberOfDigits / 2; + const left = numberAsString.slice(0, middle); + const right = numberAsString.slice(middle); + const res = [Number.parseInt(left, 10), Number.parseInt(right, 10)]; + cache.set(stone, res); + return res; + } + + const res = [stone * 2024]; + cache.set(stone, res); + return res; +} + +function blink(stones: Array) { + const newStones: number[] = []; + for (const stone of stones) { + newStones.push(...transformSingleStone(stone)); + } + return newStones; +} + +const result = blink(workerData); + +parentPort?.postMessage(result); diff --git a/2024/day-11/day11.test.ts b/2024/day-11/day11.test.ts new file mode 100644 index 0000000..e809fcf --- /dev/null +++ b/2024/day-11/day11.test.ts @@ -0,0 +1,40 @@ +import { expect, test } from "bun:test"; +import * as path from "node:path"; +import { part1, part2 } from "./day11.ts"; + +test("day 11, part 1", async () => { + const testInput = await Bun.file( + path.resolve(__dirname, "test-input.txt"), + ).text(); + const input = await Bun.file(path.resolve(__dirname, "input.txt")).text(); + + console.log("\n\n"); + + // const testResult = part1(testInput); + // console.log("Test data:", testResult); + // expect(testResult).toEqual(55312); + + const finalResult = await part1(input); + console.log("Full data:", finalResult); + expect(finalResult).toEqual(183435); + + console.log("\n\n"); +}, 10000000000000); + +test("day 11, part 2", async () => { + const testInput = await Bun.file( + path.resolve(__dirname, "test-input.txt"), + ).text(); + const input = await Bun.file(path.resolve(__dirname, "input.txt")).text(); + + const testResult = part2(testInput); + console.log("\n\n"); + console.log("Test data:", testResult); + expect(testResult).toEqual(0); + + // const finalResult = part2(input); + // console.log("Full data:", finalResult); + // expect(finalResult).toEqual(0); + + console.log("\n\n"); +}); diff --git a/2024/day-11/day11.ts b/2024/day-11/day11.ts new file mode 100644 index 0000000..bc32214 --- /dev/null +++ b/2024/day-11/day11.ts @@ -0,0 +1,35 @@ +import { Worker } from "node:worker_threads"; + +export async function part1(input: string) { + const lines = input.split("\n"); + const line = lines[0]; + const stones = line.split(" ").map(Number); + stones.length = 1; + // for (let i = 0; i < 75; i++) { + // console.log(i); + // stones = blink(stones); + // } + let final = 0; + await Promise.all( + stones.map(async (stone) => { + const sum = (await new Promise((res) => { + const worker = new Worker("./2024/day-11/workers.ts", { + workerData: stone, + }); + + worker.on("message", (result) => { + res(result); + }); + })) as number; + final += sum; + }), + ); + + return final; +} + +export function part2(input: string) { + const lines = input.split("\n"); + const final = 0; + return final; +} diff --git a/2024/day-11/input.txt b/2024/day-11/input.txt new file mode 100644 index 0000000..ae72b37 --- /dev/null +++ b/2024/day-11/input.txt @@ -0,0 +1 @@ +965842 9159 3372473 311 0 6 86213 48 \ No newline at end of file diff --git a/2024/day-11/test-input.txt b/2024/day-11/test-input.txt new file mode 100644 index 0000000..528f9d5 --- /dev/null +++ b/2024/day-11/test-input.txt @@ -0,0 +1 @@ +125 17 \ No newline at end of file diff --git a/2024/day-11/workers.ts b/2024/day-11/workers.ts new file mode 100644 index 0000000..db7441f --- /dev/null +++ b/2024/day-11/workers.ts @@ -0,0 +1,30 @@ +import { Worker, parentPort, workerData } from "node:worker_threads"; +import { chunk } from "remeda"; +let stones = [workerData]; +for (let i = 0; i < 75; i++) { + console.log(i); + const chunks = chunk(stones, 5_000_000); + const newStones = await Promise.all( + chunks.map((chunk) => processChunk(chunk)), + ); + stones = newStones.flat(1); +} + +parentPort?.postMessage(stones.length); + +async function processChunk(chunk: number[]) { + console.log("processing chunk of length", chunk.length); + return await new Promise((res) => { + const worker = new Worker("./2024/day-11/blink-worker.ts", { + workerData: chunk, + }); + + worker.on("message", (result) => { + res(result); + }); + }); +} +// async function processChunk(chunk: number[]) { +// console.log("processing chunk of length", chunk.length); +// const result = await pool.exec("blink", [chunk]); +// }