2022-17 in js
This commit is contained in:
parent
c9654e1ecc
commit
c14d3aac12
6 changed files with 431 additions and 0 deletions
44
2022/17-Pyroclastic-Flow/.eslintrc.json
Normal file
44
2022/17-Pyroclastic-Flow/.eslintrc.json
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"es2021": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:node/recommended"
|
||||||
|
],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.js"],
|
||||||
|
"rules": {
|
||||||
|
"no-constant-condition": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": "latest",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
"tab"
|
||||||
|
],
|
||||||
|
"linebreak-style": [
|
||||||
|
"error",
|
||||||
|
"unix"
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"double"
|
||||||
|
],
|
||||||
|
"semi": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"node/no-unsupported-features/es-syntax": [
|
||||||
|
"error",
|
||||||
|
{ "ignores": ["modules"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
1
2022/17-Pyroclastic-Flow/example
Normal file
1
2022/17-Pyroclastic-Flow/example
Normal file
|
@ -0,0 +1 @@
|
||||||
|
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
|
164
2022/17-Pyroclastic-Flow/first.js
Normal file
164
2022/17-Pyroclastic-Flow/first.js
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
|
function load(filename) {
|
||||||
|
let data = fs.readFileSync(filename, "utf8").trim();
|
||||||
|
const l = data.length;
|
||||||
|
let i = 0;
|
||||||
|
return {
|
||||||
|
next: function () {
|
||||||
|
const c = data[i];
|
||||||
|
i = (i + 1) % l;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const shapes = [
|
||||||
|
[0b0011110],
|
||||||
|
[0b0001000, 0b0011100, 0b0001000],
|
||||||
|
[0b0000100, 0b0000100, 0b0011100],
|
||||||
|
[0b0010000, 0b0010000, 0b0010000, 0b0010000],
|
||||||
|
[0b0011000, 0b0011000],
|
||||||
|
];
|
||||||
|
const shapes_len = shapes.length;
|
||||||
|
|
||||||
|
class Shape {
|
||||||
|
constructor(shape) {
|
||||||
|
this.shape = shape;
|
||||||
|
this.length = shape.length;
|
||||||
|
}
|
||||||
|
fall(field) { // returns true if the shape fell without colliding
|
||||||
|
for (let i=0; i<this.length; ++i) {
|
||||||
|
const next = field.get(i+1);
|
||||||
|
if (next === undefined || next & this.shape[i]) { //collision
|
||||||
|
field.solidify(this.shape);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
field.fall();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
shift(field, direction) {
|
||||||
|
let collision = false;
|
||||||
|
let tmp;
|
||||||
|
switch(direction) {
|
||||||
|
case ">":
|
||||||
|
tmp = this.shape.map(line => {
|
||||||
|
if (line & 0b1) { // we touch the right edge already
|
||||||
|
collision = true;
|
||||||
|
}
|
||||||
|
return line >>> 1;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "<":
|
||||||
|
tmp = this.shape.map(line => {
|
||||||
|
if (line & 0b1000000) { // we touch the left edge already
|
||||||
|
collision = true;
|
||||||
|
}
|
||||||
|
return line << 1;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw "invalid direction character in shape shift: " + direction;
|
||||||
|
}
|
||||||
|
if (collision) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i=0; i<this.length; ++i) {
|
||||||
|
if (field.get(i) & tmp[i]) { //collision
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.shape = tmp;
|
||||||
|
}
|
||||||
|
print() {
|
||||||
|
this.shape.forEach(line => {
|
||||||
|
console.log(
|
||||||
|
line & 0b1000000 ? "#" : ".",
|
||||||
|
line & 0b0100000 ? "#" : ".",
|
||||||
|
line & 0b0010000 ? "#" : ".",
|
||||||
|
line & 0b0001000 ? "#" : ".",
|
||||||
|
line & 0b0000100 ? "#" : ".",
|
||||||
|
line & 0b0000010 ? "#" : ".",
|
||||||
|
line & 0b0000001 ? "#" : ".",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
console.log("=======");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Shaper {
|
||||||
|
constructor() {
|
||||||
|
this.index = 0;
|
||||||
|
}
|
||||||
|
next(field) {
|
||||||
|
const s = new Shape(shapes[this.index]);
|
||||||
|
field.accomodate(shapes[this.index].length + 3);
|
||||||
|
this.index = (this.index + 1) % shapes_len;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Field {
|
||||||
|
constructor() {
|
||||||
|
this.data = [];
|
||||||
|
this.offset = 0;
|
||||||
|
}
|
||||||
|
accomodate(n) {
|
||||||
|
this.offset = 0;
|
||||||
|
for(let i=0; i<n; ++i) {
|
||||||
|
this.data.unshift(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fall() {
|
||||||
|
if (this.data[0] !== 0) { // we need to fall bellow the top line?
|
||||||
|
this.offset++;
|
||||||
|
} else {
|
||||||
|
this.data.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get(offset) {
|
||||||
|
return this.data[this.offset + offset];
|
||||||
|
}
|
||||||
|
print() {
|
||||||
|
this.data.forEach(line => {
|
||||||
|
console.log(
|
||||||
|
line & 0b1000000 ? "#" : ".",
|
||||||
|
line & 0b0100000 ? "#" : ".",
|
||||||
|
line & 0b0010000 ? "#" : ".",
|
||||||
|
line & 0b0001000 ? "#" : ".",
|
||||||
|
line & 0b0000100 ? "#" : ".",
|
||||||
|
line & 0b0000010 ? "#" : ".",
|
||||||
|
line & 0b0000001 ? "#" : ".",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
console.log("-------");
|
||||||
|
}
|
||||||
|
solidify(shape) {
|
||||||
|
for(let i=0; i<shape.length; ++i) {
|
||||||
|
this.data[i+this.offset] |= shape[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let example = load("example");
|
||||||
|
let input = load("input");
|
||||||
|
|
||||||
|
function solve(input) {
|
||||||
|
let field = new Field();
|
||||||
|
let shaper = new Shaper();
|
||||||
|
for(let i=0; i<2022; ++i) {
|
||||||
|
let shape = shaper.next(field);
|
||||||
|
do {
|
||||||
|
shape.shift(field, input.next());
|
||||||
|
} while(shape.fall(field));
|
||||||
|
}
|
||||||
|
field.print();
|
||||||
|
return field.data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const exampleOutput = solve(example);
|
||||||
|
if (exampleOutput !== 3068) {
|
||||||
|
console.log("Example failed with height " + exampleOutput);
|
||||||
|
process.exit(1); // eslint-disable-line
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(solve(input));
|
1
2022/17-Pyroclastic-Flow/input
Normal file
1
2022/17-Pyroclastic-Flow/input
Normal file
File diff suppressed because one or more lines are too long
8
2022/17-Pyroclastic-Flow/package.json
Normal file
8
2022/17-Pyroclastic-Flow/package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"eslint": "^8.30.0",
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
"jslint": "^0.12.1"
|
||||||
|
}
|
||||||
|
}
|
213
2022/17-Pyroclastic-Flow/second.js
Normal file
213
2022/17-Pyroclastic-Flow/second.js
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
|
function load(filename) {
|
||||||
|
let data = fs.readFileSync(filename, "utf8").trim();
|
||||||
|
const l = data.length;
|
||||||
|
let i = 0;
|
||||||
|
return {
|
||||||
|
next: function () {
|
||||||
|
const c = data[i];
|
||||||
|
i = (i + 1) % l;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const masks = [
|
||||||
|
0b1000000,
|
||||||
|
0b0100000,
|
||||||
|
0b0010000,
|
||||||
|
0b0001000,
|
||||||
|
0b0000100,
|
||||||
|
0b0000010,
|
||||||
|
0b0000001,
|
||||||
|
];
|
||||||
|
|
||||||
|
const shapes = [
|
||||||
|
[0b0011110],
|
||||||
|
[0b0001000, 0b0011100, 0b0001000],
|
||||||
|
[0b0000100, 0b0000100, 0b0011100],
|
||||||
|
[0b0010000, 0b0010000, 0b0010000, 0b0010000],
|
||||||
|
[0b0011000, 0b0011000],
|
||||||
|
];
|
||||||
|
const shapes_len = shapes.length;
|
||||||
|
|
||||||
|
class Shape {
|
||||||
|
constructor(shape) {
|
||||||
|
this.shape = shape;
|
||||||
|
this.length = shape.length;
|
||||||
|
}
|
||||||
|
fall(field) { // returns true if the shape fell without colliding
|
||||||
|
for (let i=0; i<this.length; ++i) {
|
||||||
|
const next = field.get(i+1);
|
||||||
|
if (next === undefined || next & this.shape[i]) { //collision
|
||||||
|
field.solidify(this.shape);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
field.fall();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
shift(field, direction) {
|
||||||
|
let collision = false;
|
||||||
|
let tmp;
|
||||||
|
switch(direction) {
|
||||||
|
case ">":
|
||||||
|
tmp = this.shape.map(line => {
|
||||||
|
if (line & 0b1) { // we touch the right edge already
|
||||||
|
collision = true;
|
||||||
|
}
|
||||||
|
return line >>> 1;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "<":
|
||||||
|
tmp = this.shape.map(line => {
|
||||||
|
if (line & 0b1000000) { // we touch the left edge already
|
||||||
|
collision = true;
|
||||||
|
}
|
||||||
|
return line << 1;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw "invalid direction character in shape shift: " + direction;
|
||||||
|
}
|
||||||
|
if (collision) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i=0; i<this.length; ++i) {
|
||||||
|
if (field.get(i) & tmp[i]) { //collision
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.shape = tmp;
|
||||||
|
}
|
||||||
|
print() {
|
||||||
|
this.shape.forEach(line => {
|
||||||
|
console.log(
|
||||||
|
line & 0b1000000 ? "#" : ".",
|
||||||
|
line & 0b0100000 ? "#" : ".",
|
||||||
|
line & 0b0010000 ? "#" : ".",
|
||||||
|
line & 0b0001000 ? "#" : ".",
|
||||||
|
line & 0b0000100 ? "#" : ".",
|
||||||
|
line & 0b0000010 ? "#" : ".",
|
||||||
|
line & 0b0000001 ? "#" : ".",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
console.log("=======");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Shaper {
|
||||||
|
constructor() {
|
||||||
|
this.index = 0;
|
||||||
|
}
|
||||||
|
next(field) {
|
||||||
|
const s = new Shape(shapes[this.index]);
|
||||||
|
field.accomodate(shapes[this.index].length + 3);
|
||||||
|
this.index = (this.index + 1) % shapes_len;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Field {
|
||||||
|
constructor() {
|
||||||
|
this.data = [];
|
||||||
|
this.offset = 0;
|
||||||
|
}
|
||||||
|
accomodate(n) {
|
||||||
|
this.offset = 0;
|
||||||
|
for(let i=0; i<n; ++i) {
|
||||||
|
this.data.unshift(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fall() {
|
||||||
|
if (this.data[0] !== 0) { // we need to fall bellow the top line?
|
||||||
|
this.offset++;
|
||||||
|
} else {
|
||||||
|
this.data.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get(offset) {
|
||||||
|
return this.data[this.offset + offset];
|
||||||
|
}
|
||||||
|
heightMap() {
|
||||||
|
const max = this.data.length;
|
||||||
|
let heights = [max, max, max, max, max, max, max];
|
||||||
|
heights.forEach((h, i) => {
|
||||||
|
for(let j=0; j<this.data.length; ++j) {
|
||||||
|
if (this.data[j] & masks[i]) {
|
||||||
|
heights[i] = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return heights;
|
||||||
|
}
|
||||||
|
print() {
|
||||||
|
this.data.forEach(line => {
|
||||||
|
console.log(
|
||||||
|
line & 0b1000000 ? "#" : ".",
|
||||||
|
line & 0b0100000 ? "#" : ".",
|
||||||
|
line & 0b0010000 ? "#" : ".",
|
||||||
|
line & 0b0001000 ? "#" : ".",
|
||||||
|
line & 0b0000100 ? "#" : ".",
|
||||||
|
line & 0b0000010 ? "#" : ".",
|
||||||
|
line & 0b0000001 ? "#" : ".",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
console.log("-------");
|
||||||
|
}
|
||||||
|
solidify(shape) {
|
||||||
|
for(let i=0; i<shape.length; ++i) {
|
||||||
|
this.data[i+this.offset] |= shape[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let example = load("example");
|
||||||
|
let input = load("input");
|
||||||
|
|
||||||
|
function solve(input) {
|
||||||
|
let field = new Field();
|
||||||
|
let shaper = new Shaper();
|
||||||
|
let height = 0;
|
||||||
|
let heightmaps = [];
|
||||||
|
const sky = 1000000000000;
|
||||||
|
for(let i=0; i<sky; ++i) {
|
||||||
|
let shape = shaper.next(field);
|
||||||
|
do {
|
||||||
|
shape.shift(field, input.next());
|
||||||
|
} while(shape.fall(field));
|
||||||
|
const heightmap = field.heightMap();
|
||||||
|
let cycle = -1;
|
||||||
|
let cycleHeight = 0;
|
||||||
|
heightmaps.forEach((h, n) => {
|
||||||
|
if (h.heightmap.every((v, idx) => v === heightmap[idx])) {
|
||||||
|
let nextCycle = heightmaps[(n+1)*2-1];
|
||||||
|
if (nextCycle !== undefined && nextCycle.heightmap.every((v, idx) => v === heightmap[idx])) {
|
||||||
|
let nextCycle2 = heightmaps[(n+1)*3-1];
|
||||||
|
if (nextCycle2 !== undefined && nextCycle2.heightmap.every((v, idx) => v === heightmap[idx])) {
|
||||||
|
cycle = n+1;
|
||||||
|
cycleHeight = field.data.length - h.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (cycle > 0) {
|
||||||
|
console.log("got cycle of", cycle, "with a height of", cycleHeight, "after", i, "iterations");
|
||||||
|
const cycles = Math.floor((sky - i) / cycle);
|
||||||
|
i += cycles * cycle;
|
||||||
|
height = cycles * cycleHeight;
|
||||||
|
console.log("computed a height of", height, "after", cycles * cycle, "additional cycles");
|
||||||
|
heightmaps = [];
|
||||||
|
}
|
||||||
|
heightmaps.unshift({ heightmap: heightmap, height: field.data.length });
|
||||||
|
}
|
||||||
|
return height + field.data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const exampleOutput = solve(example);
|
||||||
|
if (exampleOutput !== 1514285714288) {
|
||||||
|
console.log("Example failed with height " + exampleOutput, "diff is", exampleOutput - 1514285714288, "positive means too high");
|
||||||
|
process.exit(1); // eslint-disable-line
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(solve(input));
|
Loading…
Add table
Reference in a new issue