jsadvent/lib/twodee.js

124 lines
2.8 KiB
JavaScript

const Glib = require('./Glib');
const Vector = require('./Vector');
const ORIGIN = new Vector(0, 0);
const DIRECTIONS = {
UP: new Vector(0, 1),
DOWN: new Vector(0, -1),
LEFT: new Vector(-1, 0),
RIGHT: new Vector(1, 0),
};
class Rectangle {
static fromPoints(one, two) {
const [x1, x2] = [one.v[0], two.v[0]].sortInts();
const [y1, y2] = [one.v[1], two.v[1]].sortInts();
const bottomLeft = new Vector(x1, y1);
const size = bottomLeft
.multiply(-1)
.add(new Vector(x2, y2))
.add(1n);
return new Rectangle(bottomLeft, size);
}
static fromXXYY(x1, x2, y1, y2) {
return Rectangle.fromPoints(new Vector(x1, y1), new Vector(x2, y2));
}
constructor(offset, size) {
// console.log(`${offset.string} ${offset.add(size).string}`);
// todo: normalize?
this.offset = offset;
this.size = size;
}
allPoints() {
return new Glib(
(function*(_this) {
const [startX, startY] = _this.offset.toArray();
const [endX, endY] = _this.offset.add(_this.size).toArray();
for (let x = startX; x < endX; x++) {
for (let y = startY; y < endY; y++) {
yield new Vector(x, y);
}
}
})(this),
);
}
get bottomLeft() {
return this.offset;
}
get topRight() {
return this.offset.add(this.size);
}
}
class Instruction {
static fromString(string, instructionSet) {
const [char, ...num] = string.split('');
if (!instructionSet.hasOwnProperty(char)) {
throw new Error('invalid move');
}
const move = instructionSet[char];
return num.length === 0
? new Instruction(move)
: new Instruction(move, BigInt(num.join('')));
}
constructor(move, count = 1n) {
this.move = move;
this.count = count;
}
jump(source) {
// console.log(this.count);
return source.add(this.move.multiply(this.count));
}
walk(source) {
return new Glib(
(function*(_this) {
for (let i = 0n; i < _this.count; i++) {
// console.log(source.string);
source = source.add(_this.move);
yield source;
}
// console.log(source.string);
})(this),
);
}
}
module.exports = {
Instruction,
Rectangle,
DIRECTIONS,
ORIGIN,
'^v<>': {
'^': DIRECTIONS.UP,
v: DIRECTIONS.DOWN,
'<': DIRECTIONS.LEFT,
'>': DIRECTIONS.RIGHT,
},
udlr: {
u: DIRECTIONS.UP,
d: DIRECTIONS.DOWN,
l: DIRECTIONS.LEFT,
r: DIRECTIONS.RIGHT,
},
UDLR: {
U: DIRECTIONS.UP,
D: DIRECTIONS.DOWN,
L: DIRECTIONS.LEFT,
R: DIRECTIONS.RIGHT,
},
everyStep(instructions, source = ORIGIN) {
return new Glib(
(function*() {
for (const instruction of instructions) {
// console.log(instruction);
yield* instruction.walk(source);
source = instruction.jump(source);
}
})(),
);
},
};