commit c0062bef3c1e6590e98178ed81b22f2853a68ef0
parent 0d285583cd7eb162ccef53ae20164af6685ac9d3
Author: finwo <finwo@pm.me>
Date: Wed, 14 Dec 2022 10:02:10 +0100
2022/14 solution
Diffstat:
2 files changed, 204 insertions(+), 0 deletions(-)
diff --git a/2022/day-14/index.js b/2022/day-14/index.js
@@ -0,0 +1,202 @@
+const fs = require('fs');
+const through = require('through2');
+const line_by_line = require('../common/line-for-line');
+
+String.prototype.startsWith = function(subject) {
+ return this.substr(0, subject.length) === subject;
+};
+
+const grid = [];
+const entryPoint = [500, 0];
+
+function range(start, end) {
+ const ret = [];
+ const high = Math.max(start, end);
+ const low = Math.min(start, end);
+ for(let i=low; i<=high; i++) ret.push(i);
+ return low == start ? ret : ret.reverse();
+}
+
+function plot(x, y, value = 1) {
+ grid[y] = grid[y] || [];
+ grid[y][x] = value;
+}
+
+// Pulled straight out of wikipedia
+function plotLineLow(x0, y0, x1, y1) {
+ let dx = x1 - x0;
+ let dy = y1 - y0;
+ let yi = 1;
+ if (dy < 0) {
+ yi = -1;
+ dy = -dy;
+ }
+ let D = (2 * dy) - dx;
+ let y = y0;
+ for (const x of range(x0, x1)) {
+ plot(x, y);
+ if (D > 0) {
+ y = y + yi;
+ D = D + (2 * (dy - dx));
+ } else {
+ D = D + 2*dy;
+ }
+ }
+}
+function plotLineHigh(x0, y0, x1, y1) {
+ let dx = x1 - x0;
+ let dy = y1 - y0;
+ let xi = 1;
+ if (dx < 0) {
+ xi = -1;
+ dx = -dx;
+ }
+ let D = (2 * dx) - dy;
+ let x = x0;
+ for (const y of range(y0, y1)) {
+ plot(x, y);
+ if (D > 0) {
+ x = x + xi;
+ D = D + (2 * (dx - dy));
+ } else {
+ D = D + 2*dx;
+ }
+ }
+}
+function plotLine(x0, y0, x1, y1) {
+ if (Math.abs(y1 - y0) < Math.abs(x1 - x0)) {
+ if (x0 > x1) {
+ plotLineLow(x1, y1, x0, y0)
+ } else {
+ plotLineLow(x0, y0, x1, y1)
+ }
+ } else {
+ if (y0 > y1) {
+ plotLineHigh(x1, y1, x0, y0)
+ } else {
+ plotLineHigh(x0, y0, x1, y1)
+ }
+ }
+}
+
+let minx = entryPoint[0];
+let maxx = entryPoint[0];
+let miny = entryPoint[1];
+let maxy = entryPoint[1];
+
+function drawArea() {
+ // Draw area
+ for(let y=miny; y<=maxy; y++) {
+ for(let x=minx; x<=maxx; x++) {
+ if (grid[y] && grid[y][x] == 1) {
+ process.stdout.write('#');
+ } else if (grid[y] && grid[y][x] == 2) {
+ process.stdout.write('+');
+ } else if (grid[y] && grid[y][x] == 3) {
+ process.stdout.write('o');
+ } else {
+ process.stdout.write('.');
+ }
+ }
+ process.stdout.write('\n');
+ }
+}
+
+
+
+let units = 0;
+
+fs.createReadStream('input')
+ .pipe(line_by_line())
+
+ // Minor parsing
+ .pipe(through(function(line, enc, cb) {
+ line = line.toString();
+
+ // Turn into line point coordinates
+ const points = line
+ .split(' -> ')
+ .map(point => point.split(',').map(a => parseInt(a)));
+
+ // Track range to visualize later
+ points.forEach(point => {
+ minx = Math.min(minx, point[0]);
+ miny = Math.min(miny, point[1]);
+ maxx = Math.max(maxx, point[0]);
+ maxy = Math.max(maxy, point[1]);
+ });
+
+ // "draw" lines
+ let lastPoint = points.shift();
+ while(points.length) {
+ const point = points.shift();
+ plotLine(
+ lastPoint[0], lastPoint[1],
+ point[0], point[1],
+ );
+ lastPoint = point;
+ }
+
+ cb();
+ }))
+
+ .on('finish', () => {
+
+ // Mark entrypoint
+ plot(entryPoint[0], entryPoint[1], 2);
+
+ // Mark floor
+ maxy+=2;
+ plotLine(
+ minx-10000, maxy,
+ maxx+10000, maxy,
+ );
+ minx -= 10;
+ maxx += 10;
+
+ // Let sand fall in
+ while(true) {
+
+ let unit = [...entryPoint];
+
+ while(true) {
+ if (unit[1] > maxy) {
+ break;
+ }
+ if (!(grid[unit[1]+1])) {
+ unit[1]++;
+ } else if (!(grid[unit[1]+1][unit[0]])) {
+ unit[1]++;
+ } else if (!(grid[unit[1]+1][unit[0]-1])) {
+ unit[0]--;
+ unit[1]++;
+ } else if (!(grid[unit[1]+1][unit[0]+1])) {
+ unit[0]++;
+ unit[1]++;
+ } else {
+ // rest
+ break;
+ }
+ }
+
+ plot(unit[0], unit[1], 3);
+ units++;
+
+ if (units%100 == 0) {
+ drawArea();
+ process.stdout.write('\n'.repeat(3));
+ }
+
+ if (
+ (unit[1] > maxy) ||
+ (unit[0] == entryPoint[0] && unit[1] == entryPoint[1])
+ ) {
+ break;
+ }
+ }
+
+
+ drawArea();
+ console.log({ units });
+ console.log('finish');
+ });
diff --git a/2022/day-14/sample b/2022/day-14/sample
@@ -0,0 +1,2 @@
+498,4 -> 498,6 -> 496,6
+503,4 -> 502,4 -> 502,9 -> 494,9