diff --git a/day9.peggy b/day9.peggy new file mode 100644 index 0000000..e4fdfc8 --- /dev/null +++ b/day9.peggy @@ -0,0 +1,3 @@ +lines = @num+ "\n" + +num = n:$[0-9] { return parseInt(n, 10) } diff --git a/day9.ts b/day9.ts new file mode 100644 index 0000000..21cc45e --- /dev/null +++ b/day9.ts @@ -0,0 +1,114 @@ +import { type MainArgs, parseFile } from './lib/utils.ts'; + +type Parsed = number[]; + +function genBlocks(inp: Parsed): [blocks: number[], file: number] { + const blocks: number[] = []; + let file = 0; + let free = false; + let block = 0; + for (const n of inp) { + if (free) { + for (let i = 0; i < n; i++) { + blocks[block++] = NaN; + } + } else { + for (let i = 0; i < n; i++) { + blocks[block++] = file; + } + file++; + } + free = !free; + } + + return [blocks, file - 1]; +} + +function part1(inp: Parsed): number { + const [blocks, maxFile] = genBlocks(inp); + let file = maxFile; + let i = 0; + let j = blocks.length - 1; + while (i < j) { + while (i < j) { + if (isNaN(blocks[i])) { + break; + } + i++; + } + while (j > i) { + file = blocks[j]; + delete blocks[j]; + if (!isNaN(file)) { + break; + } + j--; + } + if (i < j) { + blocks[i] = file; + } else { + break; + } + } + + return blocks.reduce((t, v, n) => t + (v === undefined ? 0 : v * n), 0); +} + +function part2(inp: Parsed): number { + const [blocks, maxFile] = genBlocks(inp); + let initial = 0; + + for (let file = maxFile; file >= 0; file--) { + // TODO(hildjj): move to lastIndexOf + const start = blocks.indexOf(file, initial); + if (start === -1) { + continue; + } + let end = start; + while (end < blocks.length) { + if (blocks[++end] !== file) { + break; + } + } + + const len = end - start; + let i = initial; + initial = NaN; + + OUTER: + while (i < start) { + while (i < start) { + if (isNaN(blocks[i])) { + if (isNaN(initial)) { + initial = i; + } + break; + } + i++; + } + if (i < start) { + for (let x = i; x < i + len; x++) { + if (!isNaN(blocks[x])) { + i = x; + continue OUTER; + } + } + break; + } + } + if (i < start) { + for (let x = i; x < i + len; x++) { + blocks[x] = file; + blocks[start + x - i] = NaN; + } + i += len; + } + } + + return blocks.reduce((t, v, n) => t + (isNaN(v) ? 0 : v * n), 0); +} + +export default async function main(args: MainArgs): Promise<[number, number]> { + const inp = await parseFile(args); + return [part1(inp), part2(inp)]; +} diff --git a/inputs b/inputs index 7f179a5..6896ce8 160000 --- a/inputs +++ b/inputs @@ -1 +1 @@ -Subproject commit 7f179a501ebc3cba464c14c60f099ce151cf0089 +Subproject commit 6896ce8bdd5ac779a2236ff1c92a5be86c87379b diff --git a/test/day9.js b/test/day9.js new file mode 100644 index 0000000..a4eb94d --- /dev/null +++ b/test/day9.js @@ -0,0 +1 @@ +export default [6301895872542, 6323761685944];