diff --git a/2021/3.js b/2021/3.js new file mode 100644 index 0000000..6f2f6d3 --- /dev/null +++ b/2021/3.js @@ -0,0 +1,21 @@ +function day3(input, part2) { + let g = Grid.fromStr(input) + + if (!part2) { + let gamma = g.getColumns().map((col) => col.mode()) + let epsilon = g.getColumns().map((col) => col.antimode()) + return parseInt(gamma.join``, 2) * parseInt(epsilon.join``, 2) + } else { + let oxy = g.getRows() + let co2 = g.getRows() + + for (let i = 0; i < g.width; i++) { + let oxyBit = oxy.transpose()[i].mode((a, b) => a == 1 ? -1 : 1) + let co2Bit = co2.transpose()[i].antimode((a, b) => a == 0 ? -1 : 1) + oxy = oxy.filter((e) => e[i] == oxyBit) + co2 = co2.filter((e) => e[i] == co2Bit) + } + + return parseInt(oxy[0].join``, 2) * parseInt(co2[0].join``, 2) + } +} diff --git a/2021/4.js b/2021/4.js new file mode 100644 index 0000000..3e9d161 --- /dev/null +++ b/2021/4.js @@ -0,0 +1,34 @@ +function day4(input, part2) { + input = input.split("\n") + + let seq = input.shift().split(",").num() + let grids = input.splitOnElement("").filter((e) => e.length).map((grid) => Grid.fromStr(grid.map((line) => line.replace(/^ /, "")).join("\n"), /\s+/).mapMut((e) => [+e, false])) + + let score + + for (let num of seq) { + for (let grid of grids) { + if (grid.won) { + continue + } + + let pt = grid.findIndex((e) => e[0] == num) + + if (pt == Point.NONE) { + continue + } + + grid.set(pt, [num, true]) + + if ([...grid.getRows(), ...grid.getColumns()].some((row) => row.every((e) => e[1]))) { + grid.won = true + + if (!score || part2) { + score = grid.findAll((e) => !e[1]).map((e) => e[0]).sum() * num + } + } + } + } + + return score +} diff --git a/aoc b/aoc new file mode 100755 index 0000000..77d07a6 --- /dev/null +++ b/aoc @@ -0,0 +1,2 @@ +#!/bin/bash +NODE_INSPECT_RESUME_ON_START=1 node inspect out.js diff --git a/grid.js b/grid.js index 36fcee0..f60af32 100644 --- a/grid.js +++ b/grid.js @@ -71,12 +71,45 @@ Grid = class Grid { } } - findAll(func) { + getRows() { + return this.data.copy() + } + + getColumns() { + return this.data.transpose() + } + + findIndex(func) { + for (let y = 0; y < this.height; y++) { + for (let x = 0; x < this.width; x++) { + let pt = new Point(x, y) + if (func(this.get(pt), pt, this)) { + return pt + } + } + } + + return Point.NONE + } + + find(func) { + return this.get(this.findIndex(func)) + } + + findAllIndices(func) { let points = [] this.forEach((e, pt, grid) => func(e, pt, grid) ? points.push(pt) : 0) return points } + findAll(func) { + return this.findAllIndices(func).map((pt) => this.get(pt)) + } + + indexOf(val) { + return this.findIndex((e) => e == val) + } + contains(pt) { return pt.x >= 0 && pt.x < this.width && pt.y >= 0 && pt.y < this.height } getAdjNeighbors(pt) { return pt.getUnfilteredAdjNeighbors().filter((pt) => this.contains(pt)) } diff --git a/out.js b/out.js index 4d90d76..452f063 100644 --- a/out.js +++ b/out.js @@ -232,6 +232,8 @@ Pt = Point = class Point { toString() { return this.x + "," + this.y } } +Point.NONE = new Point(null, null) + P = function P(...args) { return new Point(...args) } @@ -310,12 +312,45 @@ Grid = class Grid { } } - findAll(func) { + getRows() { + return this.data.copy() + } + + getColumns() { + return this.data.transpose() + } + + findIndex(func) { + for (let y = 0; y < this.height; y++) { + for (let x = 0; x < this.width; x++) { + let pt = new Point(x, y) + if (func(this.get(pt), pt, this)) { + return pt + } + } + } + + return Point.NONE + } + + find(func) { + return this.get(this.findIndex(func)) + } + + findAllIndices(func) { let points = [] this.forEach((e, pt, grid) => func(e, pt, grid) ? points.push(pt) : 0) return points } + findAll(func) { + return this.findAllIndices(func).map((pt) => this.get(pt)) + } + + indexOf(val) { + return this.findIndex((e) => e == val) + } + contains(pt) { return pt.x >= 0 && pt.x < this.width && pt.y >= 0 && pt.y < this.height } getAdjNeighbors(pt) { return pt.getUnfilteredAdjNeighbors().filter((pt) => this.contains(pt)) } @@ -674,6 +709,28 @@ load = function load() { }, configurable: true }, + truthy: { + value: function() { + return this.filter((e) => e) + }, + configurable: true + }, + splitOnElement: { + value: function(sep) { + let arr = [[]] + + for (let i = 0; i < this.length; i++) { + if (this[i] == sep) { + arr.push([]) + } else { + arr[arr.length - 1].push(this[i]) + } + } + + return arr + }, + configurable: true + }, copy: { value: function() { return this.slice() @@ -687,7 +744,7 @@ load = function load() { configurable: true }, sum: { - value: function(val) { + value: function(val = 0) { return this.reduce((a, b) => a + b, val) }, configurable: true @@ -776,15 +833,17 @@ load = function load() { }, minIndex: { value: function(fn = (e) => e, tiebreak) { - let min = Infinity + let minval = Infinity + let min let idx for (let i = 0; i < this.length; i++) { let val = fn(this[i]) - if (min > val || - (min == val && tiebreak && tiebreak(min, val, idx, i) > 0)) { - min = val + if (minval > val || + (minval == val && tiebreak && tiebreak(min, this[i], idx, i) > 0)) { + minval = val + min = this[i] idx = i } } @@ -801,15 +860,17 @@ load = function load() { }, maxIndex: { value: function(fn = (e) => e, tiebreak) { - let max = -Infinity + let maxval = -Infinity + let max let idx for (let i = 0; i < this.length; i++) { let val = fn(this[i]) - if (max < val || - (max == val && tiebreak && tiebreak(max, val, idx, i) > 0)) { - max = val + if (maxval < val || + (maxval == val && tiebreak && tiebreak(max, this[i], idx, i) > 0)) { + maxval = val + max = this[i] idx = i } } @@ -851,6 +912,22 @@ load = function load() { }) Object.defineProperties(PointArray.prototype, { + splitOnElement: { + value: function(sep) { + let arr = [[]] + + for (let i = 0; i < this.length; i++) { + if (this[i].equals(sep)) { + arr.push([]) + } else { + arr[arr.length - 1].push(this[i]) + } + } + + return arr + }, + configurable: true + }, sort: { value: function(func = (a, b) => a.readingOrderCompare(b)) { return Array.prototype.sort.apply(this, func) diff --git a/proto.js b/proto.js index 57ab3cb..1385ed4 100644 --- a/proto.js +++ b/proto.js @@ -54,6 +54,28 @@ load = function load() { }, configurable: true }, + truthy: { + value: function() { + return this.filter((e) => e) + }, + configurable: true + }, + splitOnElement: { + value: function(sep) { + let arr = [[]] + + for (let i = 0; i < this.length; i++) { + if (this[i] == sep) { + arr.push([]) + } else { + arr[arr.length - 1].push(this[i]) + } + } + + return arr + }, + configurable: true + }, copy: { value: function() { return this.slice() @@ -67,7 +89,7 @@ load = function load() { configurable: true }, sum: { - value: function(val) { + value: function(val = 0) { return this.reduce((a, b) => a + b, val) }, configurable: true @@ -156,15 +178,17 @@ load = function load() { }, minIndex: { value: function(fn = (e) => e, tiebreak) { - let min = Infinity + let minval = Infinity + let min let idx for (let i = 0; i < this.length; i++) { let val = fn(this[i]) - if (min > val || - (min == val && tiebreak && tiebreak(min, val, idx, i) > 0)) { - min = val + if (minval > val || + (minval == val && tiebreak && tiebreak(min, this[i], idx, i) > 0)) { + minval = val + min = this[i] idx = i } } @@ -181,15 +205,17 @@ load = function load() { }, maxIndex: { value: function(fn = (e) => e, tiebreak) { - let max = -Infinity + let maxval = -Infinity + let max let idx for (let i = 0; i < this.length; i++) { let val = fn(this[i]) - if (max < val || - (max == val && tiebreak && tiebreak(max, val, idx, i) > 0)) { - max = val + if (maxval < val || + (maxval == val && tiebreak && tiebreak(max, this[i], idx, i) > 0)) { + maxval = val + max = this[i] idx = i } } @@ -231,6 +257,22 @@ load = function load() { }) Object.defineProperties(PointArray.prototype, { + splitOnElement: { + value: function(sep) { + let arr = [[]] + + for (let i = 0; i < this.length; i++) { + if (this[i].equals(sep)) { + arr.push([]) + } else { + arr[arr.length - 1].push(this[i]) + } + } + + return arr + }, + configurable: true + }, sort: { value: function(func = (a, b) => a.readingOrderCompare(b)) { return Array.prototype.sort.apply(this, func) diff --git a/pt.js b/pt.js index 93ef5d3..afcc247 100644 --- a/pt.js +++ b/pt.js @@ -60,6 +60,8 @@ Pt = Point = class Point { toString() { return this.x + "," + this.y } } +Point.NONE = new Point(null, null) + P = function P(...args) { return new Point(...args) }