88 lines
2.1 KiB
JavaScript
88 lines
2.1 KiB
JavaScript
const { Glib, Vector } = require('../../lib');
|
|
|
|
const DIRECTIONS = {
|
|
NORTH: 'NORTH',
|
|
SOUTH: 'SOUTH',
|
|
EAST: 'EAST',
|
|
WEST: 'WEST',
|
|
};
|
|
|
|
const TURNS = {
|
|
LEFT: 'L',
|
|
RIGHT: 'R',
|
|
};
|
|
|
|
const TURN = {
|
|
[TURNS.LEFT]: {
|
|
[DIRECTIONS.NORTH]: DIRECTIONS.WEST,
|
|
[DIRECTIONS.EAST]: DIRECTIONS.NORTH,
|
|
[DIRECTIONS.SOUTH]: DIRECTIONS.EAST,
|
|
[DIRECTIONS.WEST]: DIRECTIONS.SOUTH,
|
|
},
|
|
[TURNS.RIGHT]: {
|
|
[DIRECTIONS.NORTH]: DIRECTIONS.EAST,
|
|
[DIRECTIONS.EAST]: DIRECTIONS.SOUTH,
|
|
[DIRECTIONS.SOUTH]: DIRECTIONS.WEST,
|
|
[DIRECTIONS.WEST]: DIRECTIONS.NORTH,
|
|
},
|
|
};
|
|
|
|
const MOVE = {
|
|
[DIRECTIONS.NORTH]: new Vector(0, 1),
|
|
[DIRECTIONS.EAST]: new Vector(1, 0),
|
|
[DIRECTIONS.SOUTH]: new Vector(0, -1),
|
|
[DIRECTIONS.WEST]: new Vector(-1, 0),
|
|
};
|
|
|
|
const START = new Vector(0, 0);
|
|
|
|
const parse = (input) =>
|
|
Glib.fromIterable(input.trim().split(',')).map((i) => {
|
|
const [turn, ...distance] = i.trim();
|
|
|
|
if (turn !== TURNS.LEFT && turn !== TURNS.RIGHT) {
|
|
throw new Error('Invalid turn');
|
|
}
|
|
|
|
return {
|
|
turn,
|
|
distance: parseInt(distance.join(''), 10),
|
|
};
|
|
});
|
|
|
|
module.exports = {
|
|
'1': (input) => {
|
|
input = parse(input);
|
|
let direction = DIRECTIONS.NORTH;
|
|
let location = START;
|
|
for (const { turn, distance } of input) {
|
|
direction = TURN[turn][direction];
|
|
const moveVector = MOVE[direction].multiply(distance);
|
|
location = location.add(moveVector);
|
|
}
|
|
return START.distance(location);
|
|
},
|
|
'2': (input) => {
|
|
input = parse(input);
|
|
let direction = DIRECTIONS.NORTH;
|
|
let location = START;
|
|
|
|
let visited = new Set();
|
|
for (const { turn, distance } of input) {
|
|
direction = TURN[turn][direction];
|
|
const destination = location.add(MOVE[direction].multiply(distance))
|
|
.string;
|
|
let locStr = location.string;
|
|
while (locStr != destination) {
|
|
if (visited.has(locStr)) {
|
|
return START.distance(location);
|
|
}
|
|
visited.add(locStr);
|
|
location = location.add(MOVE[direction]);
|
|
locStr = location.string;
|
|
}
|
|
}
|
|
},
|
|
parse,
|
|
};
|