diff --git a/nine/src/bruteforce.js b/nine/src/bruteforce.js new file mode 100644 index 0000000..03f6d30 --- /dev/null +++ b/nine/src/bruteforce.js @@ -0,0 +1,97 @@ +import { readFile } from 'node:fs/promises' +import { resolve } from 'node:path' + +const pipe = (...fns) => x => fns.reduce((val, fn) => fn(val), x) +const add = (a, b) => a + b +const sum = list => list.reduce(add, 0n) +const toInt = n => parseInt(n, 10) + +function* scanLeft(xs) { + for (let i = 0, j = 0; i < xs.length; i++) { + const token = xs[i] + const value = i % 2 ? -1 : i / 2 + + for (let k = 0; k < token; k++, j++) { + yield value + } + } +} + +function* scanRight(xs) { + const len = xs.length - 1 + for (let i = len; i > 0; i--) { + const token = xs[i] + const value = i % 2 ? -1 : i / 2 + + for (let j = token; j > 0; j--) { + yield value + } + } +} + +const expand = input => { + const tokens = Array.isArray(input) ? input : input.split('') + const ints = tokens.map(toInt) + return [scanLeft(ints), scanRight(ints), sum(tokens.map(BigInt))] +} + +function* defrag([fwd, bwd, len]) { + const swaps = new Set() + let i = 0n + let j = len - 1n + let a = fwd.next() + let b = bwd.next() + + for (i, a; !a.done; a = fwd.next(), i += 1n) { + const x = a.value + if (swaps.has(i)) { + yield -1 + swaps.delete(i) + continue + } else if (x !== -1) { + yield x + continue + } else if (j <= i) { + yield x + continue + } + + while (!b.done) { + const y = b.value + if (j <= i) { break } + + if (y > -1) { + swaps.add(j) + yield y + b = bwd.next() + j -= 1n + break + } + + b = bwd.next() + j -= 1n + } + } +} + +const checksum = iter => { + let acc = 0 + + let j = 0 + for (const value of iter) { + const skip = value === -1 + acc += skip ? 0 : j * value + + if (!skip) { + j++ + } + } + + return acc +} + +const main = pipe(expand, defrag, checksum) + +readFile(resolve('./input'), { encoding: 'utf8' }) + .then(main) + .then(console.log)