121 lines
2.7 KiB
JavaScript
121 lines
2.7 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);
|
|
}
|
|
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);
|
|
}
|
|
})(),
|
|
);
|
|
},
|
|
};
|