diff --git a/2021/day-02/index.js b/2021/day-02/index.js new file mode 100644 index 0000000..af7e035 --- /dev/null +++ b/2021/day-02/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-unused-vars +const console = require('../helpers') +require('./solution') diff --git a/2021/day-02/input.txt b/2021/day-02/input.txt new file mode 100644 index 0000000..d5c08db --- /dev/null +++ b/2021/day-02/input.txt @@ -0,0 +1,1000 @@ +forward 9 +forward 9 +forward 3 +down 2 +forward 8 +down 8 +forward 1 +down 6 +down 9 +down 9 +forward 1 +up 5 +up 4 +up 8 +down 6 +down 7 +forward 4 +forward 6 +forward 2 +forward 2 +forward 4 +down 2 +down 6 +forward 6 +forward 9 +up 4 +up 6 +down 2 +forward 7 +up 7 +down 8 +down 4 +down 6 +forward 1 +down 2 +up 1 +forward 8 +down 9 +forward 6 +up 9 +down 8 +forward 5 +forward 8 +down 8 +up 3 +up 9 +down 2 +down 2 +forward 5 +up 7 +forward 5 +down 6 +forward 4 +down 2 +up 2 +up 7 +up 1 +down 4 +down 8 +forward 6 +down 2 +forward 7 +down 1 +forward 7 +forward 1 +up 1 +down 4 +down 3 +down 4 +down 4 +up 8 +down 1 +up 7 +forward 8 +down 5 +up 1 +down 4 +down 3 +forward 4 +up 7 +forward 1 +down 4 +down 2 +down 4 +up 8 +up 6 +down 1 +up 3 +down 5 +forward 4 +down 3 +forward 9 +down 9 +forward 2 +down 4 +up 3 +down 4 +forward 1 +forward 7 +forward 9 +forward 7 +forward 3 +forward 6 +down 4 +forward 7 +down 5 +down 1 +forward 7 +up 1 +down 8 +down 7 +down 7 +down 7 +down 3 +forward 4 +forward 6 +forward 6 +forward 1 +down 7 +down 6 +down 8 +up 5 +down 7 +up 6 +forward 9 +down 7 +down 1 +down 9 +forward 8 +up 5 +down 6 +forward 3 +up 2 +down 1 +forward 2 +down 3 +up 6 +forward 8 +forward 1 +forward 3 +down 9 +forward 1 +down 3 +up 7 +forward 8 +up 8 +down 7 +down 2 +forward 3 +up 7 +forward 6 +down 7 +down 6 +up 5 +forward 9 +down 7 +up 5 +forward 6 +up 5 +up 6 +forward 6 +down 8 +down 1 +forward 7 +forward 6 +down 5 +down 6 +forward 9 +down 6 +up 5 +forward 9 +forward 4 +down 1 +forward 5 +down 4 +forward 5 +forward 1 +down 1 +forward 4 +down 5 +forward 4 +up 8 +down 1 +forward 6 +down 5 +forward 8 +forward 8 +forward 5 +down 7 +down 4 +forward 4 +up 1 +up 8 +down 6 +up 5 +forward 6 +forward 5 +forward 9 +down 3 +down 5 +forward 3 +down 6 +forward 6 +up 7 +up 6 +down 6 +down 1 +forward 8 +forward 9 +up 5 +forward 8 +forward 9 +forward 9 +down 2 +down 8 +forward 8 +down 2 +up 8 +down 2 +down 2 +up 1 +down 5 +down 6 +down 1 +down 8 +down 9 +forward 3 +forward 2 +down 6 +up 8 +forward 9 +forward 7 +forward 1 +down 8 +up 8 +forward 8 +down 5 +down 3 +up 3 +forward 6 +forward 5 +down 4 +forward 4 +down 4 +forward 5 +forward 9 +forward 2 +forward 9 +down 1 +down 3 +down 6 +forward 6 +down 7 +forward 3 +forward 4 +forward 1 +down 6 +forward 1 +forward 4 +forward 2 +forward 2 +forward 1 +forward 2 +down 1 +up 2 +forward 1 +down 3 +forward 8 +down 3 +down 9 +forward 5 +down 3 +down 3 +forward 2 +forward 9 +down 9 +forward 4 +down 2 +forward 5 +up 8 +down 4 +forward 5 +down 1 +forward 9 +down 1 +forward 7 +forward 2 +down 2 +down 6 +up 3 +forward 7 +up 4 +forward 7 +forward 6 +down 8 +forward 2 +down 3 +forward 9 +forward 4 +forward 8 +down 6 +forward 8 +down 9 +down 2 +down 3 +forward 1 +down 5 +down 3 +forward 2 +forward 7 +down 4 +down 3 +forward 9 +down 2 +forward 2 +forward 1 +up 6 +up 4 +down 5 +forward 5 +up 8 +down 7 +forward 6 +down 5 +forward 3 +forward 3 +forward 7 +up 9 +up 6 +down 5 +up 7 +forward 2 +forward 5 +down 9 +down 6 +forward 7 +down 9 +up 2 +up 5 +forward 1 +forward 8 +forward 9 +up 8 +forward 9 +forward 5 +up 9 +down 4 +down 7 +forward 2 +forward 1 +down 4 +up 8 +down 5 +down 7 +down 9 +down 3 +down 9 +up 8 +up 7 +up 8 +down 8 +down 2 +down 6 +down 6 +up 5 +up 9 +forward 1 +down 8 +up 4 +up 3 +forward 7 +up 7 +down 3 +up 1 +forward 3 +down 7 +forward 8 +forward 2 +down 6 +down 2 +up 7 +up 5 +forward 7 +forward 1 +forward 6 +up 6 +forward 5 +down 2 +up 4 +forward 2 +down 9 +forward 6 +forward 3 +forward 3 +forward 4 +forward 2 +down 6 +forward 9 +forward 7 +down 4 +up 1 +forward 4 +down 6 +down 6 +up 1 +up 1 +forward 3 +down 5 +up 5 +down 3 +down 6 +up 8 +down 2 +up 6 +up 1 +forward 8 +up 6 +down 8 +forward 9 +forward 4 +forward 9 +down 7 +down 9 +down 6 +down 1 +forward 9 +forward 9 +down 6 +down 5 +up 6 +down 9 +up 4 +up 5 +forward 8 +down 4 +down 5 +forward 8 +forward 7 +down 2 +forward 2 +forward 6 +forward 7 +down 1 +down 7 +down 1 +down 6 +forward 2 +up 2 +down 4 +down 8 +forward 1 +down 1 +down 3 +down 3 +up 9 +down 9 +forward 3 +up 4 +forward 1 +down 9 +down 8 +down 9 +forward 5 +forward 4 +up 3 +down 8 +forward 2 +down 3 +up 5 +forward 4 +down 7 +down 8 +down 9 +forward 8 +down 8 +forward 4 +down 6 +down 3 +forward 5 +down 3 +down 9 +down 4 +up 8 +forward 4 +up 6 +down 3 +forward 6 +down 9 +down 7 +forward 7 +forward 3 +forward 2 +forward 4 +down 4 +down 5 +up 9 +down 2 +down 6 +down 9 +forward 7 +forward 3 +up 3 +forward 3 +down 4 +down 7 +forward 2 +down 2 +forward 3 +down 8 +down 7 +down 7 +forward 2 +forward 2 +up 6 +forward 8 +forward 9 +up 3 +forward 8 +forward 5 +forward 7 +up 3 +forward 3 +forward 6 +down 5 +down 5 +down 4 +forward 1 +forward 8 +forward 4 +forward 3 +down 1 +forward 8 +down 4 +up 5 +forward 4 +down 2 +forward 7 +down 2 +forward 9 +down 1 +forward 6 +forward 8 +forward 6 +forward 7 +forward 1 +forward 6 +down 5 +up 3 +forward 7 +down 6 +forward 2 +down 2 +forward 8 +forward 9 +up 7 +forward 1 +forward 1 +up 1 +forward 1 +down 2 +forward 6 +down 9 +up 1 +up 2 +forward 6 +forward 1 +forward 7 +down 1 +up 8 +forward 7 +up 6 +up 4 +down 1 +forward 2 +down 4 +down 1 +down 7 +down 4 +up 3 +forward 8 +forward 3 +forward 5 +down 7 +down 8 +forward 5 +forward 2 +down 5 +down 2 +forward 2 +up 9 +down 3 +down 5 +up 7 +down 4 +down 2 +down 7 +forward 6 +down 2 +forward 1 +up 4 +forward 2 +forward 2 +down 5 +down 1 +down 1 +forward 7 +forward 6 +down 7 +down 5 +up 1 +up 3 +forward 3 +forward 9 +forward 4 +down 1 +down 5 +forward 3 +forward 7 +down 8 +forward 8 +forward 2 +forward 7 +up 7 +down 7 +down 4 +down 2 +up 6 +up 1 +forward 8 +up 8 +up 6 +down 8 +forward 1 +down 5 +forward 3 +down 3 +down 3 +forward 1 +up 3 +up 3 +forward 8 +forward 8 +down 8 +forward 6 +forward 2 +down 7 +forward 8 +down 7 +up 5 +forward 7 +down 1 +forward 9 +up 6 +down 2 +up 2 +up 5 +forward 6 +forward 9 +forward 3 +down 8 +forward 8 +down 2 +up 5 +down 9 +forward 5 +down 6 +down 3 +down 9 +up 8 +up 3 +down 2 +forward 7 +forward 4 +forward 4 +forward 8 +up 6 +up 4 +forward 9 +down 6 +down 8 +up 3 +up 5 +forward 8 +forward 7 +forward 4 +down 8 +forward 1 +forward 5 +down 9 +forward 8 +up 6 +down 6 +down 8 +down 2 +forward 4 +forward 9 +forward 2 +forward 7 +down 3 +forward 3 +up 6 +down 4 +forward 2 +up 4 +down 4 +forward 4 +forward 3 +forward 1 +up 6 +forward 1 +down 1 +forward 7 +up 4 +forward 3 +down 4 +up 6 +up 2 +up 8 +down 1 +down 6 +down 6 +down 1 +down 7 +forward 8 +down 9 +forward 5 +up 2 +up 7 +up 5 +down 6 +up 1 +up 6 +forward 4 +down 7 +forward 5 +forward 1 +down 6 +forward 2 +down 2 +forward 9 +down 9 +up 6 +forward 1 +up 7 +down 7 +forward 1 +down 6 +up 1 +forward 2 +forward 1 +down 4 +forward 9 +forward 7 +forward 5 +down 1 +forward 2 +down 2 +down 2 +down 5 +forward 1 +up 8 +forward 9 +down 7 +forward 9 +down 2 +up 5 +down 9 +down 8 +down 5 +forward 8 +forward 4 +down 4 +down 6 +forward 1 +down 5 +up 6 +down 3 +down 3 +forward 9 +down 9 +forward 6 +down 5 +up 6 +down 5 +up 7 +forward 9 +down 2 +down 4 +down 8 +forward 4 +up 7 +forward 9 +forward 7 +up 5 +down 7 +down 5 +down 1 +forward 5 +forward 4 +down 2 +up 3 +forward 1 +up 4 +up 9 +down 4 +forward 3 +down 4 +down 9 +forward 4 +up 2 +up 3 +forward 7 +up 6 +down 8 +down 8 +forward 6 +forward 2 +forward 3 +forward 9 +forward 7 +down 6 +down 7 +down 4 +down 2 +forward 8 +down 6 +forward 6 +forward 6 +forward 9 +down 8 +down 1 +up 5 +down 1 +forward 9 +down 1 +up 8 +forward 8 +down 3 +forward 1 +down 9 +forward 6 +forward 4 +forward 8 +down 2 +up 8 +down 2 +up 8 +down 9 +down 4 +up 7 +forward 7 +forward 5 +down 5 +down 4 +up 8 +forward 1 +down 7 +forward 1 +up 9 +forward 9 +forward 7 +forward 9 +down 9 +forward 4 +down 7 +forward 6 +forward 6 +up 3 +forward 2 +down 5 +up 8 +down 1 +up 8 +down 4 +down 1 +up 6 +forward 4 +forward 3 +forward 6 +down 3 +forward 4 +forward 4 +forward 4 +down 8 +forward 3 +up 8 +up 8 +down 8 +forward 6 +forward 8 +up 5 +forward 6 +down 8 +down 7 +up 4 +forward 6 +forward 9 +down 9 +forward 4 +up 2 +forward 1 +up 3 +down 9 +down 8 +forward 8 +forward 8 +forward 7 +down 6 +down 1 +up 6 +up 6 +forward 9 +forward 7 +forward 7 +down 3 +down 6 +down 9 +down 4 +forward 7 +forward 3 +forward 3 +down 7 +up 5 +down 3 +forward 6 +forward 3 +forward 5 +up 3 +down 7 +forward 2 +up 7 +forward 9 +down 3 +down 9 +forward 8 +forward 5 +up 7 +up 2 +up 8 +forward 6 +down 8 +forward 2 +forward 4 +up 2 +forward 2 +forward 8 +forward 4 +down 8 +forward 5 +down 4 +down 7 +forward 3 +down 3 +up 1 +down 9 +forward 9 +down 2 +down 1 +forward 1 +down 6 +down 3 +forward 5 +down 3 +down 8 +up 7 +down 1 +up 9 +down 4 +forward 9 +down 4 +forward 3 +forward 6 +down 3 +forward 3 +down 2 +down 7 +down 1 +up 4 +down 9 +down 1 +down 3 +down 4 +down 8 +down 7 +forward 4 +down 4 +down 9 +forward 2 +forward 7 +forward 2 +down 6 +up 8 +forward 6 +down 2 +forward 6 +up 8 +forward 6 +down 9 +forward 2 +forward 6 diff --git a/2021/day-02/navigate.js b/2021/day-02/navigate.js new file mode 100644 index 0000000..d119a4e --- /dev/null +++ b/2021/day-02/navigate.js @@ -0,0 +1,54 @@ +const move = (location, direction, distance) => { + const result = location + switch (direction) { + case 'forward': + result.x += distance + break + case 'up': + result.d -= distance + break + case 'down': + result.d += distance + break + default: + throw new Error(`Direction ${direction} is unsupported`) + } + return result +} + +const navigate = (location, route, useAiming = false) => { + let position = location + route.forEach(instruction => { + if (useAiming) { + position = aimedMove(position, instruction[0], instruction[1]) + } else { + position = move(position, instruction[0], instruction[1]) + } + }) + return position +} + +const aimedMove = (location, direction, distance) => { + const result = location + switch (direction) { + case 'forward': + result.x += distance + result.d += (distance * location.a) + break + case 'up': + result.a -= distance + break + case 'down': + result.a += distance + break + default: + throw new Error(`Direction ${direction} is unsupported`) + } + return result +} + +module.exports = { + move, + navigate, + aimedMove +} diff --git a/2021/day-02/navigate.test.js b/2021/day-02/navigate.test.js new file mode 100644 index 0000000..45980ff --- /dev/null +++ b/2021/day-02/navigate.test.js @@ -0,0 +1,94 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { move, navigate, aimedMove } = require('./navigate') + +const TestRoute = [ + ['forward', 5], + ['down', 5], + ['forward', 8], + ['up', 3], + ['down', 8], + ['forward', 2] +] + +describe('--- Day 2: Dive! ---', () => { + describe('Part 1', () => { + describe('move()', () => { + it('moves the submarine forward', () => { + expect(move({ x: 0, d: 0 }, 'forward', 8)).to.deep.equal({ + x: 8, + d: 0 + }) + }) + it('moves the submarine down', () => { + expect(move({ x: 0, d: 0 }, 'down', 8)).to.deep.equal({ + x: 0, + d: 8 + }) + }) + it('moves the submarine up', () => { + expect(move({ x: 0, d: 0 }, 'up', 8)).to.deep.equal({ + x: 0, + d: -8 + }) + }) + it('throws an error for an unexpected direction', () => { + expect(() => { + move({ x: 0, d: 0 }, 'garbage', 5) + }).to.throw('Direction garbage is unsupported') + }) + }) + describe('navigate()', () => { + it('takes a series of directions and follows the route', () => { + expect(navigate({ x: 0, d: 0 }, TestRoute)).to.deep.equal({ + x: 15, + d: 10 + }) + }) + }) + }) + describe('Part 2', () => { + describe('aimedMove()', () => { + it('moves forward when the aim is 0', () => { + expect(aimedMove({ x: 0, d: 0, a: 0 }, 'forward', 5)).to.deep.equal({ + x: 5, + d: 0, + a: 0 + }) + }) + it('aims down without moving', () => { + expect(aimedMove({ x: 0, d: 0, a: 0 }, 'down', 5)).to.deep.equal({ + x: 0, + d: 0, + a: 5 + }) + }) + it('moves forward and down when aimed', () => { + expect(aimedMove({ x: 0, d: 0, a: 5 }, 'forward', 8)).to.deep.equal({ + x: 8, + d: 40, + a: 5 + }) + }) + it('aims up without moving', () => { + expect(aimedMove({ x: 0, d: 0, a: 5 }, 'up', 3)).to.deep.equal({ + x: 0, + d: 0, + a: 2 + }) + }) + it('throws an error for an unexpected direction', () => { + expect(() => { + aimedMove({ x: 0, d: 0, a: 5 }, 'garbage', 5) + }).to.throw('Direction garbage is unsupported') + }) + }) + describe('navigate()', () => { + it('can navigate using aiming', () => { + const destination = navigate({ x: 0, d: 0, a: 0 }, TestRoute, true) + expect(destination.x).to.equal(15) + expect(destination.d).to.equal(60) + }) + }) + }) +}) diff --git a/2021/day-02/solution.js b/2021/day-02/solution.js new file mode 100644 index 0000000..bbf27d3 --- /dev/null +++ b/2021/day-02/solution.js @@ -0,0 +1,42 @@ +const fs = require('fs') +const path = require('path') +const filePath = path.join(__dirname, 'input.txt') +const { linesToArray } = require('../../2018/inputParser') +const { navigate } = require('./navigate') + +fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { + if (err) throw err + + initData = linesToArray(initData.trim()).map(command => { + const tmp = command.split(' ') + return [ + tmp[0], + parseInt(tmp[1]) + ] + }) + + const resetInput = () => { + // Deep copy to ensure we aren't mutating the original data + return JSON.parse(JSON.stringify(initData)) + } + + const part1 = () => { + const data = resetInput() + const destination = navigate({ x: 0, d: 0 }, data) + return destination.x * destination.d + } + + const part2 = () => { + const data = resetInput() + const destination = navigate({ x: 0, d: 0, a: 0 }, data, true) + return destination.x * destination.d + } + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +}) diff --git a/index.js b/index.js index c0d3680..fe32819 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -require('./2021/day-01/solution') +require('./2021/day-02/solution')