diff --git a/.aocrunner.json b/.aocrunner.json index ada1d8f..f79913c 100644 --- a/.aocrunner.json +++ b/.aocrunner.json @@ -227,16 +227,16 @@ }, { "part1": { - "solved": false, - "result": null, + "solved": true, + "result": "852", "attempts": [], - "time": null + "time": 0.78 }, "part2": { - "solved": false, - "result": null, + "solved": true, + "result": "19348959966392", "attempts": [], - "time": null + "time": 0.62 } }, { diff --git a/README.md b/README.md index 723e57b..669eaf6 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ [![Day](https://badgen.net/badge/13/%E2%98%85%E2%98%85/green)](src/day13) [![Day](https://badgen.net/badge/14/%E2%98%85%E2%98%85/green)](src/day14) [![Day](https://badgen.net/badge/15/%E2%98%85%E2%98%85/green)](src/day15) -![Day](https://badgen.net/badge/16/%E2%98%86%E2%98%86/gray) +[![Day](https://badgen.net/badge/16/%E2%98%85%E2%98%85/green)](src/day16) ![Day](https://badgen.net/badge/17/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/18/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/19/%E2%98%86%E2%98%86/gray) @@ -167,16 +167,16 @@ Both parts: 6.279999999999999ms ``` Day 15 -Time part 1: 8.12ms -Time part 2: 769.36ms -Both parts: 777.48ms +Time part 1: 55.8ms +Time part 2: 761.32ms +Both parts: 817.12ms ``` ``` Day 16 -Time part 1: - -Time part 2: - -Both parts: - +Time part 1: 0.78ms +Time part 2: 0.62ms +Both parts: 1.4ms ``` ``` @@ -243,8 +243,8 @@ Both parts: - ``` ``` -Total stars: 30/50 -Total time: 1861.9599999999996ms +Total stars: 32/50 +Total time: 1902.9999999999998ms ``` diff --git a/src/day16/index.js b/src/day16/index.js index fbf670b..ba1e30b 100644 --- a/src/day16/index.js +++ b/src/day16/index.js @@ -11,75 +11,128 @@ function b2d(binaryString) { return parseInt(binaryString, 2) } -const part1 = (rawInput) => { - const input = parseInput(rawInput) - let cursor = 0, - ans = 0 +function readPacket1(s) { + if (/^0+$/.test(s)) return [0, ""] + let cursor = 0 function read(n) { cursor += n - return input.substr(cursor - n, n) + return s.substr(cursor - n, n) } - const stack = [{ count: 1 }] - while (stack.length) { - const thisLimit = stack[0] - if (thisLimit.count !== undefined) { - --thisLimit.count - if (thisLimit.count == 0) { - stack.shift() - } + const version = b2d(read(3)) + const typeId = b2d(read(3)) + if (typeId === 4) { + // literal value + let acc = "" + for (let more = 1; more; ) { + more = +read(1) + acc += read(4) } - if (thisLimit.cursor !== undefined) { - if (cursor >= thisLimit.cursor) { - stack.shift() - } - } - const version = b2d(read(3)) - const typeId = b2d(read(3)) - if (typeId === 4) { - // literal value - ans += version - let acc = "" - for (let more = 1; more; ) { - more = +read(1) - acc += read(4) + return [version, s.substr(cursor)] + } else { + // operator type + const lengthTypeId = +read(1) + if (lengthTypeId == 0) { + const subpacketLength = b2d(read(15)) + let nextV, nextS = read(subpacketLength) + let versionSum = version + while (nextS.length > 0) { + [nextV, nextS] = readPacket1(nextS) + versionSum += nextV } + return [versionSum, s.substr(cursor)] } else { - // operator type - const lengthTypeId = +read(1) - if (lengthTypeId == 0) { - const subpacketLength = b2d(read(15)) - ans += version - stack.unshift({ cursor: cursor + subpacketLength }) - } else { - const subpacketCount = b2d(read(11)) - ans += version - stack.unshift({ count: subpacketCount }) + const subpacketCount = b2d(read(11)) + let nextV, nextS = s.substr(cursor) + let versionSum = version + for (let i = 0; i < subpacketCount; i++) { + [nextV, nextS] = readPacket1(nextS) + versionSum += nextV } + return [versionSum, nextS] + } + } +} + +const part1 = (rawInput) => { + const input = parseInput(rawInput) + return readPacket1(input)[0] +} + +const operators = [ + (...args) => args.reduce((a,c) => a+c, 0), // sum, + (...args) => args.reduce((a,c) => a*c, 1), // product + Math.min, // minimum, + Math.max, // maximum, + null, // omitted + (a,b) => a > b ? 1 : 0, // greater than + (a,b) => a < b ? 1 : 0, // less than + (a,b) => a == b ? 1 : 0, // equals +] + +function readPacket2(s) { + if (/^0+$/.test(s)) return [undefined, ""] + let cursor = 0 + function read(n) { + cursor += n + return s.substr(cursor - n, n) + } + read(3) // version, read and discard + const typeId = b2d(read(3)) + if (typeId === 4) { + // literal value + let acc = "" + for (let more = 1; more; ) { + more = +read(1) + acc += read(4) + } + return [parseInt(acc, 2), s.substr(cursor)] + } else { + // operator type + const lengthTypeId = +read(1) + if (lengthTypeId == 0) { + const subpacketLength = b2d(read(15)) + const values = [] + let nextValue, nextS = read(subpacketLength) + while (nextS.length > 0) { + [nextValue, nextS] = readPacket2(nextS) + values.push(nextValue) + } + return [operators[typeId](...values), s.substr(cursor)] + } else { + const subpacketCount = b2d(read(11)) + const values = [] + let nextValue, nextS = s.substr(cursor) + for (let i = 0; i < subpacketCount; i++) { + [nextValue, nextS] = readPacket2(nextS) + values.push(nextValue) + } + return [operators[typeId](...values), nextS] } } - return ans } const part2 = (rawInput) => { const input = parseInput(rawInput) - - return + return readPacket2(input)[0] } run({ part1: { tests: [ { input: `D2FE28`, expected: 6 }, - // { input: `8A004A801A8002F478`, expected: 16 }, - // { input: `620080001611562C8802118E34`, expected: 12 }, - // { input: `C0015000016115A2E0802F182340`, expected: 23 }, - // { input: `A0016C880162017C3686B18A3D4780`, expected: 31 }, + { input: `8A004A801A8002F478`, expected: 16 }, + { input: `620080001611562C8802118E34`, expected: 12 }, + { input: `C0015000016115A2E0802F182340`, expected: 23 }, + { input: `A0016C880162017C3686B18A3D4780`, expected: 31 }, ], solution: part1, }, part2: { tests: [ - // { input: ``, expected: "" }, + { input: `C200B40A82`, expected: 3 }, + { input: `04005AC33890`, expected: 54 }, + { input: `880086C3E88112`, expected: 7 }, + { input: `CE00C43D881120`, expected: 9 }, ], solution: part2, },