-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #132 from amclin/feat/2020-day-10
Feat/2020 day 10
- Loading branch information
Showing
5 changed files
with
282 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// eslint-disable-next-line no-unused-vars | ||
const console = require('../helpers') | ||
require('./solution') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
const countDifferences = (data) => { | ||
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]++ | ||
}) | ||
console.debug('Tallied voltage differences:', tallies) | ||
return tallies | ||
} | ||
|
||
const countCombinations = (data) => { | ||
const tallies = Array(5).fill(0) | ||
const delta = (idx) => { | ||
return data[idx] - data[idx - 1] | ||
} | ||
|
||
// 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 = { | ||
countDifferences, | ||
countCombinations | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* eslint-env mocha */ | ||
const { expect } = require('chai') | ||
const { countDifferences, countCombinations } = require('./jolts') | ||
|
||
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', () => { | ||
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) | ||
}) | ||
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 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) | ||
}) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
const fs = require('fs') | ||
const path = require('path') | ||
const filePath = path.join(__dirname, 'input.txt') | ||
const { inputToArray } = require('../../2018/inputParser') | ||
const { countDifferences, countCombinations } = require('./jolts') | ||
|
||
fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { | ||
if (err) throw err | ||
|
||
initData = inputToArray(initData.trim()).map(Number) | ||
|
||
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 differences = countDifferences(data) | ||
return differences[1] * differences[3] | ||
} | ||
|
||
const part2 = () => { | ||
const data = resetInput() | ||
return countCombinations(data) | ||
} | ||
const answers = [] | ||
answers.push(part1()) | ||
answers.push(part2()) | ||
|
||
answers.forEach((ans, idx) => { | ||
console.info(`-- Part ${idx + 1} --`) | ||
console.info(`Answer: ${ans}`) | ||
}) | ||
}) |