Skip to content

Commit 18b7582

Browse files
Merge pull request #132 from amclin/feat/2020-day-10
Feat/2020 day 10
2 parents b3cf433 + e21b7c1 commit 18b7582

File tree

5 files changed

+282
-0
lines changed

5 files changed

+282
-0
lines changed

2020/day-10/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// eslint-disable-next-line no-unused-vars
2+
const console = require('../helpers')
3+
require('./solution')

2020/day-10/input.txt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
47
2+
99
3+
115
4+
65
5+
10
6+
55
7+
19
8+
73
9+
80
10+
100
11+
71
12+
110
13+
64
14+
135
15+
49
16+
3
17+
1
18+
98
19+
132
20+
2
21+
38
22+
118
23+
66
24+
116
25+
104
26+
87
27+
79
28+
114
29+
40
30+
37
31+
44
32+
97
33+
4
34+
140
35+
60
36+
86
37+
56
38+
133
39+
7
40+
146
41+
85
42+
111
43+
134
44+
53
45+
121
46+
77
47+
117
48+
21
49+
12
50+
81
51+
145
52+
129
53+
107
54+
93
55+
22
56+
48
57+
11
58+
54
59+
92
60+
78
61+
67
62+
20
63+
138
64+
125
65+
57
66+
96
67+
26
68+
147
69+
124
70+
34
71+
74
72+
143
73+
13
74+
28
75+
126
76+
50
77+
29
78+
70
79+
39
80+
63
81+
41
82+
91
83+
32
84+
84
85+
144
86+
27
87+
139
88+
33
89+
88
90+
72
91+
23
92+
103
93+
16

2020/day-10/jolts.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
const countDifferences = (data) => {
2+
const tallies = Array(4).fill(0)
3+
// Always account for the outlet
4+
data.push(0)
5+
// Always add the native adapter at the end
6+
tallies[3]++
7+
8+
// Iterate through the adapters
9+
data.sort((a, b) => a - b)
10+
.forEach((curr, idx) => {
11+
if (!data[idx + 1]) {
12+
// end of array, nothing to do
13+
return
14+
}
15+
const next = data[idx + 1]
16+
const delta = next - curr
17+
if (delta > 3) {
18+
// Problem with data. Gap in joltages greater than allowed
19+
throw new Error(`Joltage difference between ${curr} and ${next} is greater than allowed.`)
20+
}
21+
22+
console.debug(`Joltage difference between ${curr} and ${next} is ${delta}.`)
23+
tallies[delta]++
24+
})
25+
console.debug('Tallied voltage differences:', tallies)
26+
return tallies
27+
}
28+
29+
const countCombinations = (data) => {
30+
const tallies = Array(5).fill(0)
31+
const delta = (idx) => {
32+
return data[idx] - data[idx - 1]
33+
}
34+
35+
// Always account for the outlet
36+
data.push(0)
37+
data = data.sort((a, b) => a - b)
38+
39+
const deltas = data.reduce((res, el, idx) => {
40+
console.debug(idx, el, delta(idx))
41+
if (idx <= 0) {
42+
return res
43+
}
44+
res.push(delta(idx))
45+
return res
46+
}, [])
47+
console.debug('joltage deltas', deltas)
48+
49+
// I'm really not proud of this solution. It hardcodes too much logic with magic constants
50+
// and only works because there are no joltage differences of 2, and the max allowed
51+
// skip is 3.
52+
//
53+
// Since the rules say adapters can support 1, 2, or 3 jolt diferences,
54+
// that means if the difference between n and n+2 is 3 or less, n+1 can be safely
55+
// skipped. Potentially we can skip two.
56+
// Every time we skip a number, the total amount of variations doubles
57+
58+
// This logic would be a LOT messier if we had diffs of 2 in the data set
59+
60+
// When we have 2 skips in a row, we need to leave one combo in case
61+
// skipping both exceeds the max difference
62+
// TODO: we aren't implementing this because our data set doesn't have
63+
// any diffs of 2, which means we never have a 1 + 2 skip to worry about
64+
65+
// When we have 3 skips in a row, we're definitely exceeding the max difference
66+
// if the next is also a skip so we have to leave at least one in place
67+
68+
// When we have 5 skips in a row.... etc..
69+
// TODO: we aren't implementing this because dataset doesn't have any examples
70+
71+
deltas.forEach((d, idx, arr) => {
72+
if (d === 1 && arr[idx + 1] === 1 && arr[idx + 2] === 1 && arr[idx + 3] === 1) {
73+
console.debug('Found 4 in a row')
74+
tallies[4]++
75+
deltas.splice(idx, 4)
76+
} else if (d === 1 && arr[idx + 1] === 1 && arr[idx + 2] === 1) {
77+
console.debug('Found 3 in a row')
78+
tallies[3]++
79+
deltas.splice(idx, 3)
80+
} else if (d === 1 && arr[idx + 1] === 1) {
81+
console.debug('Found 2 in a row')
82+
tallies[2]++
83+
deltas.splice(idx, 2)
84+
} else if (d === 1) {
85+
console.debug('Found 1 in a row')
86+
tallies[1]++
87+
deltas.splice(idx, 1)
88+
}
89+
})
90+
91+
console.debug('skippable ranges', tallies)
92+
console.debug([1, 1 ** tallies[1], 2 ** tallies[2], 4 ** tallies[3], 7 ** tallies[4]])
93+
return (
94+
1 ** tallies[1]
95+
) * (
96+
2 ** tallies[2]
97+
) * (
98+
4 ** tallies[3]
99+
) * (
100+
7 ** tallies[4] // 4 in a row is special case because we can't skip more than 3
101+
)
102+
}
103+
104+
module.exports = {
105+
countDifferences,
106+
countCombinations
107+
}

2020/day-10/jolts.test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/* eslint-env mocha */
2+
const { expect } = require('chai')
3+
const { countDifferences, countCombinations } = require('./jolts')
4+
5+
const srcAdapters = [
6+
[16, 10, 15, 5, 1, 11, 7, 19, 6, 12, 4],
7+
[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]
8+
]
9+
10+
describe('--- Day 10: Adapter Array ---', () => {
11+
let adapters
12+
beforeEach(() => {
13+
// reset test data since arrays get mutated using a quick-and-dirty deep copy
14+
adapters = JSON.parse(JSON.stringify(srcAdapters))
15+
})
16+
describe('Part 1', () => {
17+
describe('countDifferences()', () => {
18+
it('tabulates the amoount of joltage differences in the adapter set', () => {
19+
const result = countDifferences(adapters[0])
20+
expect(result[1]).to.equal(7)
21+
expect(result[3]).to.equal(5)
22+
const result2 = countDifferences(adapters[1])
23+
expect(result2[1]).to.equal(22)
24+
expect(result2[3]).to.equal(10)
25+
})
26+
it('throws an error if any joltage differences exceed 3', () => {
27+
expect(() => countDifferences([5, 40])).to.throw()
28+
})
29+
it('throws an error if any joltage differences is less than 1', () => {
30+
expect(() => countDifferences([5, 5])).to.throw()
31+
})
32+
})
33+
})
34+
describe('Part 2', () => {
35+
describe('countCombinations()', () => {
36+
it('tabulates the amount of adapter combinations in the set', () => {
37+
const result = countCombinations(adapters[0])
38+
expect(result).to.equal(8)
39+
const result2 = countCombinations(adapters[1])
40+
expect(result2).to.equal(19208)
41+
})
42+
})
43+
})
44+
})

2020/day-10/solution.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
const filePath = path.join(__dirname, 'input.txt')
4+
const { inputToArray } = require('../../2018/inputParser')
5+
const { countDifferences, countCombinations } = require('./jolts')
6+
7+
fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => {
8+
if (err) throw err
9+
10+
initData = inputToArray(initData.trim()).map(Number)
11+
12+
const resetInput = () => {
13+
// Deep copy to ensure we aren't mutating the original data
14+
return JSON.parse(JSON.stringify(initData))
15+
}
16+
17+
const part1 = () => {
18+
const data = resetInput()
19+
const differences = countDifferences(data)
20+
return differences[1] * differences[3]
21+
}
22+
23+
const part2 = () => {
24+
const data = resetInput()
25+
return countCombinations(data)
26+
}
27+
const answers = []
28+
answers.push(part1())
29+
answers.push(part2())
30+
31+
answers.forEach((ans, idx) => {
32+
console.info(`-- Part ${idx + 1} --`)
33+
console.info(`Answer: ${ans}`)
34+
})
35+
})

0 commit comments

Comments
 (0)