From 55cc0993d2898c7720751c3c6e32b41839e619f7 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Fri, 18 Dec 2020 15:09:15 -0800 Subject: [PATCH 1/7] feat(2020-day-10): stub out day 10 --- 2020/day-10/index.js | 3 +++ 2020/day-10/input.txt | 0 2020/day-10/solution.js | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 2020/day-10/index.js create mode 100644 2020/day-10/input.txt create mode 100644 2020/day-10/solution.js diff --git a/2020/day-10/index.js b/2020/day-10/index.js new file mode 100644 index 0000000..af7e035 --- /dev/null +++ b/2020/day-10/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-unused-vars +const console = require('../helpers') +require('./solution') diff --git a/2020/day-10/input.txt b/2020/day-10/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/2020/day-10/solution.js b/2020/day-10/solution.js new file mode 100644 index 0000000..779f7ea --- /dev/null +++ b/2020/day-10/solution.js @@ -0,0 +1,35 @@ +const fs = require('fs') +const path = require('path') +const filePath = path.join(__dirname, 'input.txt') +const { inputToArray } = require('../../2018/inputParser') + +fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { + if (err) throw err + + initData = inputToArray(initData.trim()) + + const resetInput = () => { + // Deep copy to ensure we aren't mutating the original data + return JSON.parse(JSON.stringify(initData)) + } + + const part1 = () => { + const data = resetInput() + console.debug(data) + return 'No answer yet' + } + + const part2 = () => { + const data = resetInput() + console.debug(data) + return 'No answer yet' + } + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +}) From 94cf63b6dc02783380686c7e22f57e912d38c0b8 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Fri, 18 Dec 2020 15:12:50 -0800 Subject: [PATCH 2/7] test(2020-day-10): define tests for joltage difference detection --- 2020/day-10/jolts.js | 10 ++++++++++ 2020/day-10/jolts.test.js | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 2020/day-10/jolts.js create mode 100644 2020/day-10/jolts.test.js diff --git a/2020/day-10/jolts.js b/2020/day-10/jolts.js new file mode 100644 index 0000000..46ef94d --- /dev/null +++ b/2020/day-10/jolts.js @@ -0,0 +1,10 @@ +const countDifferences = (data) => { + if (data.length > 15) { + return [0, 22, 0, 10] + } + return [0, 7, 0, 5] +} + +module.exports = { + countDifferences +} diff --git a/2020/day-10/jolts.test.js b/2020/day-10/jolts.test.js new file mode 100644 index 0000000..81f68bd --- /dev/null +++ b/2020/day-10/jolts.test.js @@ -0,0 +1,23 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { countDifferences } = require('./jolts') + +const adapters = [ + [16, 10, 15, 5, 1, 11, 7, 19, 6, 12, 4], + [28, 33, 18, 42, 31, 14, 46, 20, 48, 47, 24, 23, 49, 45, 19, 38, 39, 11, 1, 32, 25, 35, 8, 17, 7, 9, 4, 2, 34, 10, 3] +] + +describe('--- Day 10: Adapter Array ---', () => { + describe('Part 1', () => { + describe('countDifferences()', () => { + it('tabulates the amoount of joltage differences in the adapter set', () => { + const result = countDifferences(adapters[0]) + expect(result[1]).to.equal(7) + expect(result[3]).to.equal(5) + const result2 = countDifferences(adapters[1]) + expect(result2[1]).to.equal(22) + expect(result2[3]).to.equal(10) + }) + }) + }) +}) From 308ddca8837e98fae5e2619023967eaf1858b75f Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Fri, 18 Dec 2020 15:31:25 -0800 Subject: [PATCH 3/7] feat(2020-day-10): tally up the voltage differences across the set of adapters --- 2020/day-10/jolts.js | 29 +++++++++++++++++++++++++---- 2020/day-10/jolts.test.js | 3 +++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/2020/day-10/jolts.js b/2020/day-10/jolts.js index 46ef94d..c21b9bb 100644 --- a/2020/day-10/jolts.js +++ b/2020/day-10/jolts.js @@ -1,8 +1,29 @@ const countDifferences = (data) => { - if (data.length > 15) { - return [0, 22, 0, 10] - } - return [0, 7, 0, 5] + const tallies = Array(4).fill(0) + // Always account for the outlet + data.push(0) + // Always add the native adapter at the end + tallies[3]++ + + // Iterate through the adapters + data.sort((a, b) => a - b) + .forEach((curr, idx) => { + if (!data[idx + 1]) { + // end of array, nothing to do + return + } + const next = data[idx + 1] + const delta = next - curr + if (delta > 3) { + // Problem with data. Gap in joltages greater than allowed + throw new Error(`Joltage difference between ${curr} and ${next} is greater than allowed.`) + } + + console.debug(`Joltage difference between ${curr} and ${next} is ${delta}.`) + tallies[delta]++ + }) + + return tallies } module.exports = { diff --git a/2020/day-10/jolts.test.js b/2020/day-10/jolts.test.js index 81f68bd..922b27e 100644 --- a/2020/day-10/jolts.test.js +++ b/2020/day-10/jolts.test.js @@ -18,6 +18,9 @@ describe('--- Day 10: Adapter Array ---', () => { expect(result2[1]).to.equal(22) expect(result2[3]).to.equal(10) }) + it('throws an error if any joltage differences exceed 3', () => { + expect(() => countDifferences([5, 40])).to.throw() + }) }) }) }) From dd5d94c4832e1fff3992bbe9ba0a94e69e363ceb Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Fri, 18 Dec 2020 15:33:54 -0800 Subject: [PATCH 4/7] feat(2020-day-10): find the voltage differences to solve for part 1 --- 2020/day-10/input.txt | 93 +++++++++++++++++++++++++++++++++++++++++ 2020/day-10/solution.js | 8 ++-- 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/2020/day-10/input.txt b/2020/day-10/input.txt index e69de29..dc30936 100644 --- a/2020/day-10/input.txt +++ b/2020/day-10/input.txt @@ -0,0 +1,93 @@ +47 +99 +115 +65 +10 +55 +19 +73 +80 +100 +71 +110 +64 +135 +49 +3 +1 +98 +132 +2 +38 +118 +66 +116 +104 +87 +79 +114 +40 +37 +44 +97 +4 +140 +60 +86 +56 +133 +7 +146 +85 +111 +134 +53 +121 +77 +117 +21 +12 +81 +145 +129 +107 +93 +22 +48 +11 +54 +92 +78 +67 +20 +138 +125 +57 +96 +26 +147 +124 +34 +74 +143 +13 +28 +126 +50 +29 +70 +39 +63 +41 +91 +32 +84 +144 +27 +139 +33 +88 +72 +23 +103 +16 \ No newline at end of file diff --git a/2020/day-10/solution.js b/2020/day-10/solution.js index 779f7ea..dcddc47 100644 --- a/2020/day-10/solution.js +++ b/2020/day-10/solution.js @@ -1,12 +1,14 @@ +const { count } = require('console') const fs = require('fs') const path = require('path') const filePath = path.join(__dirname, 'input.txt') const { inputToArray } = require('../../2018/inputParser') +const { countDifferences } = require('./jolts') fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { if (err) throw err - initData = inputToArray(initData.trim()) + initData = inputToArray(initData.trim()).map(Number) const resetInput = () => { // Deep copy to ensure we aren't mutating the original data @@ -15,8 +17,8 @@ fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { const part1 = () => { const data = resetInput() - console.debug(data) - return 'No answer yet' + const differences = countDifferences(data) + return differences[1] * differences[3] } const part2 = () => { From 76def6be7933c34fb878e0b81d9c0aaa650ffa36 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Fri, 18 Dec 2020 15:52:35 -0800 Subject: [PATCH 5/7] test(2020-day-10): test cases for finding the number of combinations --- 2020/day-10/jolts.js | 10 +++++++++- 2020/day-10/jolts.test.js | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/2020/day-10/jolts.js b/2020/day-10/jolts.js index c21b9bb..cb37b49 100644 --- a/2020/day-10/jolts.js +++ b/2020/day-10/jolts.js @@ -26,6 +26,14 @@ const countDifferences = (data) => { return tallies } +const countCombinations = (data) => { + if (data.length > 15) { + return 19208 + } + return 8 +} + module.exports = { - countDifferences + countDifferences, + countCombinations } diff --git a/2020/day-10/jolts.test.js b/2020/day-10/jolts.test.js index 922b27e..43b1b09 100644 --- a/2020/day-10/jolts.test.js +++ b/2020/day-10/jolts.test.js @@ -1,6 +1,6 @@ /* eslint-env mocha */ const { expect } = require('chai') -const { countDifferences } = require('./jolts') +const { countDifferences, countCombinations } = require('./jolts') const adapters = [ [16, 10, 15, 5, 1, 11, 7, 19, 6, 12, 4], @@ -23,4 +23,17 @@ describe('--- Day 10: Adapter Array ---', () => { }) }) }) + describe('Part 2', () => { + describe('countCombinations()', () => { + it('tabulates the amoount of adapter combinations in the set', () => { + const result = countCombinations(adapters[0]) + expect(result).to.equal(8) + const result2 = countCombinations(adapters[1]) + expect(result2).to.equal(19208) + }) + it('throws an error if any joltage differences exceed 3', () => { + expect(() => countDifferences([5, 40])).to.throw() + }) + }) + }) }) From 9000f2f32197f9a58a13957bf8c60e6a136ba1b8 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Fri, 18 Dec 2020 15:53:02 -0800 Subject: [PATCH 6/7] perf(2020-day-10): remove unused import --- 2020/day-10/solution.js | 1 - 1 file changed, 1 deletion(-) diff --git a/2020/day-10/solution.js b/2020/day-10/solution.js index dcddc47..1bb5283 100644 --- a/2020/day-10/solution.js +++ b/2020/day-10/solution.js @@ -1,4 +1,3 @@ -const { count } = require('console') const fs = require('fs') const path = require('path') const filePath = path.join(__dirname, 'input.txt') From e21b7c1bfd8a09e530819a9adbc7abf94ee261de Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Sun, 20 Dec 2020 13:35:18 -0800 Subject: [PATCH 7/7] feat(2020-day-10): count combinations to solve part 2 nasty nasty hackish solution. but it works :( --- 2020/day-10/jolts.js | 76 ++++++++++++++++++++++++++++++++++++--- 2020/day-10/jolts.test.js | 15 +++++--- 2020/day-10/solution.js | 5 ++- 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/2020/day-10/jolts.js b/2020/day-10/jolts.js index cb37b49..bdb45fe 100644 --- a/2020/day-10/jolts.js +++ b/2020/day-10/jolts.js @@ -22,15 +22,83 @@ const countDifferences = (data) => { console.debug(`Joltage difference between ${curr} and ${next} is ${delta}.`) tallies[delta]++ }) - + console.debug('Tallied voltage differences:', tallies) return tallies } const countCombinations = (data) => { - if (data.length > 15) { - return 19208 + const tallies = Array(5).fill(0) + const delta = (idx) => { + return data[idx] - data[idx - 1] } - return 8 + + // Always account for the outlet + data.push(0) + data = data.sort((a, b) => a - b) + + const deltas = data.reduce((res, el, idx) => { + console.debug(idx, el, delta(idx)) + if (idx <= 0) { + return res + } + res.push(delta(idx)) + return res + }, []) + console.debug('joltage deltas', deltas) + + // I'm really not proud of this solution. It hardcodes too much logic with magic constants + // and only works because there are no joltage differences of 2, and the max allowed + // skip is 3. + // + // Since the rules say adapters can support 1, 2, or 3 jolt diferences, + // that means if the difference between n and n+2 is 3 or less, n+1 can be safely + // skipped. Potentially we can skip two. + // Every time we skip a number, the total amount of variations doubles + + // This logic would be a LOT messier if we had diffs of 2 in the data set + + // When we have 2 skips in a row, we need to leave one combo in case + // skipping both exceeds the max difference + // TODO: we aren't implementing this because our data set doesn't have + // any diffs of 2, which means we never have a 1 + 2 skip to worry about + + // When we have 3 skips in a row, we're definitely exceeding the max difference + // if the next is also a skip so we have to leave at least one in place + + // When we have 5 skips in a row.... etc.. + // TODO: we aren't implementing this because dataset doesn't have any examples + + deltas.forEach((d, idx, arr) => { + if (d === 1 && arr[idx + 1] === 1 && arr[idx + 2] === 1 && arr[idx + 3] === 1) { + console.debug('Found 4 in a row') + tallies[4]++ + deltas.splice(idx, 4) + } else if (d === 1 && arr[idx + 1] === 1 && arr[idx + 2] === 1) { + console.debug('Found 3 in a row') + tallies[3]++ + deltas.splice(idx, 3) + } else if (d === 1 && arr[idx + 1] === 1) { + console.debug('Found 2 in a row') + tallies[2]++ + deltas.splice(idx, 2) + } else if (d === 1) { + console.debug('Found 1 in a row') + tallies[1]++ + deltas.splice(idx, 1) + } + }) + + console.debug('skippable ranges', tallies) + console.debug([1, 1 ** tallies[1], 2 ** tallies[2], 4 ** tallies[3], 7 ** tallies[4]]) + return ( + 1 ** tallies[1] + ) * ( + 2 ** tallies[2] + ) * ( + 4 ** tallies[3] + ) * ( + 7 ** tallies[4] // 4 in a row is special case because we can't skip more than 3 + ) } module.exports = { diff --git a/2020/day-10/jolts.test.js b/2020/day-10/jolts.test.js index 43b1b09..c2d5bd7 100644 --- a/2020/day-10/jolts.test.js +++ b/2020/day-10/jolts.test.js @@ -2,12 +2,17 @@ const { expect } = require('chai') const { countDifferences, countCombinations } = require('./jolts') -const adapters = [ +const srcAdapters = [ [16, 10, 15, 5, 1, 11, 7, 19, 6, 12, 4], [28, 33, 18, 42, 31, 14, 46, 20, 48, 47, 24, 23, 49, 45, 19, 38, 39, 11, 1, 32, 25, 35, 8, 17, 7, 9, 4, 2, 34, 10, 3] ] describe('--- Day 10: Adapter Array ---', () => { + let adapters + beforeEach(() => { + // reset test data since arrays get mutated using a quick-and-dirty deep copy + adapters = JSON.parse(JSON.stringify(srcAdapters)) + }) describe('Part 1', () => { describe('countDifferences()', () => { it('tabulates the amoount of joltage differences in the adapter set', () => { @@ -21,19 +26,19 @@ describe('--- Day 10: Adapter Array ---', () => { it('throws an error if any joltage differences exceed 3', () => { expect(() => countDifferences([5, 40])).to.throw() }) + it('throws an error if any joltage differences is less than 1', () => { + expect(() => countDifferences([5, 5])).to.throw() + }) }) }) describe('Part 2', () => { describe('countCombinations()', () => { - it('tabulates the amoount of adapter combinations in the set', () => { + it('tabulates the amount of adapter combinations in the set', () => { const result = countCombinations(adapters[0]) expect(result).to.equal(8) const result2 = countCombinations(adapters[1]) expect(result2).to.equal(19208) }) - it('throws an error if any joltage differences exceed 3', () => { - expect(() => countDifferences([5, 40])).to.throw() - }) }) }) }) diff --git a/2020/day-10/solution.js b/2020/day-10/solution.js index 1bb5283..1e53861 100644 --- a/2020/day-10/solution.js +++ b/2020/day-10/solution.js @@ -2,7 +2,7 @@ const fs = require('fs') const path = require('path') const filePath = path.join(__dirname, 'input.txt') const { inputToArray } = require('../../2018/inputParser') -const { countDifferences } = require('./jolts') +const { countDifferences, countCombinations } = require('./jolts') fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { if (err) throw err @@ -22,8 +22,7 @@ fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { const part2 = () => { const data = resetInput() - console.debug(data) - return 'No answer yet' + return countCombinations(data) } const answers = [] answers.push(part1())