From 4ee438f8d67a516d7506ea52076793a1930c1c70 Mon Sep 17 00:00:00 2001 From: nim-ka Date: Sat, 19 Nov 2022 02:26:18 +0000 Subject: [PATCH] . --- 2021/10.js | 32 ++++++------ 2021/14.js | 2 +- 2021/16.js | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2021/17.js | 38 ++++++++++++++ 2021/18.js | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++ out.js | 13 +++++ proto.js | 12 +++++ utils.js | 1 + 8 files changed, 364 insertions(+), 18 deletions(-) create mode 100644 2021/16.js create mode 100644 2021/17.js create mode 100644 2021/18.js diff --git a/2021/10.js b/2021/10.js index 7ec12ce..5ae7196 100644 --- a/2021/10.js +++ b/2021/10.js @@ -3,24 +3,22 @@ const closes = [")", "]", "}", ">"] const scores1 = { ")": 3, "]": 57, "}": 1197, ">": 25137 } const scores2 = { ")": 1, "]": 2, "}": 3, ">": 4 } -function parse(str) { - let stack = [] - - for (let i = 0; i < str.length; i++) { - let char = str[i] - - if (opens.includes(char)) { - stack.push(closes[opens.indexOf(char)]) - } else if (char != stack.pop()) { - return scores1[char] - } - } - - return stack.reverse() -} - function day10(input, part2) { - let results = input.split("\n").map(parse) + let results = input.split("\n").map((str) => { + let stack = [] + + for (let i = 0; i < str.length; i++) { + let char = str[i] + + if (opens.includes(char)) { + stack.push(closes[opens.indexOf(char)]) + } else if (char != stack.pop()) { + return scores1[char] + } + } + + return stack.reverse() + }) if (!part2) { return results.filter((e) => !Array.isArray(e)).sum() diff --git a/2021/14.js b/2021/14.js index e220c1b..ec5b9b9 100644 --- a/2021/14.js +++ b/2021/14.js @@ -31,7 +31,7 @@ function day14(input, part2) { counts = Object.keys(counts).map((key) => [key.split(""), counts[key]]) - let letters = counts.map((e) => e[0]).flat().uniq().map((letter) => (counts.filter((e) => e[0].includes(letter)).map((e) => e[0].count(letter) * e[1]).sum() + (letter == init[0] || letter == init[init.length - 1])) / 2) + let letters = counts.flatMap((e) => e[0]).uniq().map((letter) => (counts.filter((e) => e[0].includes(letter)).map((e) => e[0].count(letter) * e[1]).sum() + (letter == init[0] || letter == init[init.length - 1])) / 2) return letters.max() - letters.min() } diff --git a/2021/16.js b/2021/16.js new file mode 100644 index 0000000..5180b14 --- /dev/null +++ b/2021/16.js @@ -0,0 +1,140 @@ +function toInt(bits) { + return parseInt(bits.join(""), 2) +} + +class Packet { + full = [] + + version = [] + type = [] + groups = [[]] + lengthType = [] + length = [] + + children = [] + done = false + + constructor(bits = []) { + for (let bit of bits) { + this.pushBit(bit) + } + } + + pushBit(bit) { + if (this.version.length < 3) { + this.version.push(bit) + return this.full.push(bit) + } + + if (this.type.length < 3) { + this.type.push(bit) + return this.full.push(bit) + } + + if (this.isLiteral()) { + if (this.groups.last.length < 5) { + this.groups.last.push(bit) + return this.full.push(bit) + } + + if (this.groups.last[0]) { + this.groups.push([bit]) + return this.full.push(bit) + } + } else { + if (this.children.length == 0) { + this.children.push(new Packet()) + } + + if (this.lengthType.length < 1) { + this.lengthType.push(bit) + return this.full.push(bit) + } + + if (!this.lengthType[0]) { + if (this.length.length < 15) { + this.length.push(bit) + return this.full.push(bit) + } + + if (this.children.map((e) => e.full.length).sum() < toInt(this.length)) { + this.children.last.pushBit(bit) + + if (this.children.last.done) { + this.children.push(new Packet([bit])) + } + + return this.full.push(bit) + } + } else { + if (this.length.length < 11) { + this.length.push(bit) + return this.full.push(bit) + } + + if (!this.children.last.done) { + this.children.last.pushBit(bit) + + if (this.children.last.done) { + if (this.children.length < toInt(this.length)) { + this.children.push(new Packet([bit])) + return this.full.push(bit) + } + } else { + return this.full.push(bit) + } + } + } + } + + this.done = true + } + + isLiteral() { + return toInt(this.type) == 4 + } + + getLiteralValue() { + return toInt(this.groups.flatMap((e) => e.slice(1))) + } + + getVersionSum() { + return toInt(this.version) + this.children.map((e) => e.getVersionSum()).sum() + } + + getValue() { + if (this.isLiteral()) { + return this.getLiteralValue() + } else { + let operands = this.children.map((e) => e.getValue()) + + switch (toInt(this.type)) { + case 0: + return operands.sum() + + case 1: + return operands.prod() + + case 2: + return operands.min() + + case 3: + return operands.max() + + case 5: + return +(operands[0] > operands[1]) + + case 6: + return +(operands[0] < operands[1]) + + case 7: + return +(operands[0] == operands[1]) + } + } + } +} + +function day16(input, part2) { + let bits = input.split("").flatMap((e) => parseInt(e, 16).toString(2).padStart(4, "0").split("").num()) + return new Packet(bits)[part2 ? "getValue" : "getVersionSum"]() +} diff --git a/2021/17.js b/2021/17.js new file mode 100644 index 0000000..d4a94b5 --- /dev/null +++ b/2021/17.js @@ -0,0 +1,38 @@ +function day17(input, part2) { + let [minX, maxX, minY, maxY] = input.match(/([-\d]+)/g).num() + + let xVelRange = utils.signAgnosticInclusiveRange(0, maxX) + let yVelRange = utils.signAgnosticInclusiveRange(-minY, minY) + + let vels = xVelRange.cartProduct(yVelRange).map((e) => new Point(...e)).pt.filter((e) => { + let pos = new Point(0, 0) + let vel = e.copy() + + while (pos.x <= maxX && pos.y >= minY) { + if (pos.x >= minX && pos.y <= maxY) { + return true + } + + pos.addMut(vel) + + if (vel.x > 0) { + vel.x-- + } + + vel.y-- + + if (vel.y == 0) { + e.maxYPos = pos.y + } + } + + return false + }) + + if (!part2) { + // i feel like this is probably equivalent to minY * (minY + 1) / 2 but im not 100% sure for all inputs + return vels.max((e) => e.y).maxYPos + } else { + return vels.length + } +} diff --git a/2021/18.js b/2021/18.js new file mode 100644 index 0000000..61039e7 --- /dev/null +++ b/2021/18.js @@ -0,0 +1,144 @@ +class SnailfishNumber { + static fromArr(arr, parent = null, isRight) { + let num = new SnailfishNumber() + return num.initialize( + arr[0] instanceof Array ? SnailfishNumber.fromArr(arr[0], num, false) : arr[0], + arr[1] instanceof Array ? SnailfishNumber.fromArr(arr[1], num, true) : arr[1], + parent, isRight) + } + + initialize(left, right, parent, isRight) { + this.left = left + this.right = right + this.parent = parent + this.isRight = isRight + return this + } + + explode(depth = 0) { + if (this.left instanceof SnailfishNumber) { + if (this.left.explode(depth + 1)) { + return true + } + } + + if (this.right instanceof SnailfishNumber) { + if (this.right.explode(depth + 1)) { + return true + } + } + + if (!(this.left instanceof SnailfishNumber) && !(this.right instanceof SnailfishNumber) && depth >= 4) { + let lastNode = this + let node = this.parent + + while (node && node.left == lastNode) { + lastNode = node + node = node.parent + } + + if (node) { + if (!(node.left instanceof SnailfishNumber)) { + node.left += this.left + } else { + node = node.left + + while (node.right instanceof SnailfishNumber) { + node = node.right + } + + node.right += this.left + } + } + + lastNode = this + node = this.parent + + while (node && node.right == lastNode) { + lastNode = node + node = node.parent + } + + if (node) { + if (!(node.right instanceof SnailfishNumber)) { + node.right += this.right + } else { + node = node.right + + while (node.left instanceof SnailfishNumber) { + node = node.left + } + + node.left += this.right + } + } + + if (!this.isRight) { + this.parent.left = 0 + } else { + this.parent.right = 0 + } + + return true + } + + return false + } + + split() { + if (this.left instanceof SnailfishNumber) { + if (this.left.split()) { + return true + } + } else if (this.left >= 10) { + this.left = SnailfishNumber.fromArr([Math.floor(this.left / 2), Math.ceil(this.left / 2)], this, false) + return true + } + + if (this.right instanceof SnailfishNumber) { + if (this.right.split()) { + return true + } + } else if (this.right >= 10) { + this.right = SnailfishNumber.fromArr([Math.floor(this.right / 2), Math.ceil(this.right / 2)], this, true) + return true + } + + return false + } + + reduce() { + while (this.explode() || this.split()); + return this + } + + add(that) { + let parent = SnailfishNumber.fromArr([this, that]) + this.parent = parent + this.isRight = false + that.parent = parent + that.isRight = true + return parent.reduce() + } + + magnitude() { + return 3 * (this.left instanceof SnailfishNumber ? this.left.magnitude() : this.left) + + 2 * (this.right instanceof SnailfishNumber ? this.right.magnitude() : this.right) + } + + toString() { + return "[" + this.left.toString() + "," + this.right.toString() + "]" + } +} + +function day18(input, part2) { + let lines = input.split("\n") + + if (!part2) { + let nums = lines.map((line) => SnailfishNumber.fromArr(JSON.parse(line))) + return nums.reduce((a, b) => a.add(b)).magnitude() + } else { + let pairs = lines.flatMap((e) => lines.filter((f) => e != f).map((f) => [e, f].map((e) => SnailfishNumber.fromArr(JSON.parse(e))))) + return pairs.map((e) => e[0].add(e[1]).magnitude()).max() + } +} diff --git a/out.js b/out.js index 1faad35..8016de8 100644 --- a/out.js +++ b/out.js @@ -768,6 +768,18 @@ load = function load() { }, configurable: true }, + prod: { + value: function(val = 1) { + return this.reduce((a, b) => a * b, val) + }, + configurable: true + }, + cartProduct: { + value: function(that) { + return this.flatMap((e) => that.map((f) => [e, f])) + }, + configurable: true + }, flatDeep: { value: function() { return this.flat(Infinity) @@ -1029,6 +1041,7 @@ load = function load() { load() utils = { + log: (e, copy = false) => (console.log(copy ? e.copyDeep() : e), e), fetch: (url) => fetch(url).then(e => e.text()), fetchEval: (url) => utils.fetch(url).then(e => eval(e)), signAgnosticInclusiveRange: (a, b, s = Math.sign(a - b)) => Array((a - b) * s + 1).fill().map((_, i) => a - i * s), diff --git a/proto.js b/proto.js index c367f17..f8fbd31 100644 --- a/proto.js +++ b/proto.js @@ -102,6 +102,18 @@ load = function load() { }, configurable: true }, + prod: { + value: function(val = 1) { + return this.reduce((a, b) => a * b, val) + }, + configurable: true + }, + cartProduct: { + value: function(that) { + return this.flatMap((e) => that.map((f) => [e, f])) + }, + configurable: true + }, flatDeep: { value: function() { return this.flat(Infinity) diff --git a/utils.js b/utils.js index 3a80263..c858944 100644 --- a/utils.js +++ b/utils.js @@ -1,4 +1,5 @@ utils = { + log: (e, copy = false) => (console.log(copy ? e.copyDeep() : e), e), fetch: (url) => fetch(url).then(e => e.text()), fetchEval: (url) => utils.fetch(url).then(e => eval(e)), signAgnosticInclusiveRange: (a, b, s = Math.sign(a - b)) => Array((a - b) * s + 1).fill().map((_, i) => a - i * s),