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, };