Skip to content

Commit fa113b6

Browse files
Merge pull request #206 from amclin/feat/2021-day-08
Feat/2021 day 08
2 parents 556767c + caa74ac commit fa113b6

File tree

8 files changed

+819
-3
lines changed

8 files changed

+819
-3
lines changed

Diff for: 2021/day-08/display.js

+469
Large diffs are not rendered by default.

Diff for: 2021/day-08/display.test.js

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/* eslint-env mocha */
2+
const { expect } = require('chai')
3+
const { descrambleSignal, decodeSignal, parseEntry } = require('./display')
4+
5+
const testSingle = 'acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf'
6+
7+
const testMultiple = `be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
8+
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
9+
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
10+
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
11+
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
12+
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
13+
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
14+
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
15+
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
16+
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce`.split('\n')
17+
18+
describe('--- Day 8: Seven Segment Search ---', () => {
19+
describe('Part 1', () => {
20+
describe('descrambleSignal()', () => {
21+
const testData = testSingle.split('|')[0].trim()
22+
const { segmentCodes, charCodes } = descrambleSignal(testData)
23+
24+
it('takes scambled string of 10 codes and identifies the letters matching each seven-digit-display segment', () => {
25+
expect(segmentCodes.length).to.equal(7)
26+
expect(segmentCodes.filter((code) => !['a', 'b', 'c', 'd', 'e', 'f', 'g'].includes(code)).length).to.equal(0)
27+
})
28+
29+
it('produces a list of character codes for each number that can be displayed', () => {
30+
// There should be exactly 10 numbers
31+
expect(charCodes.length).to.equal(10)
32+
// lengths of each code is predictable as each number has a specific count of segments
33+
const expectedLengths = [6, 2, 5, 5, 4, 5, 6, 3, 7, 6]
34+
expect(charCodes.map(code => code.length)).to.deep.equal(expectedLengths)
35+
})
36+
})
37+
describe('decodeSignal()', () => {
38+
const testData = testMultiple[0].split('|').map((a) => a.trim())
39+
const { charCodes } = descrambleSignal(testData[0])
40+
41+
it('decodes a display pattern using the provided map of display codes', () => {
42+
const result = decodeSignal(charCodes, testData[1])
43+
expect(result[0]).to.equal(8)
44+
expect(result[3]).to.equal(4)
45+
})
46+
it('throws an error if a digit doesn`t have a matching code', () => {
47+
expect(
48+
() => decodeSignal(
49+
[['a']],
50+
'dcb'
51+
)
52+
).to.throw(
53+
'No match found for dcb when cleaned up to b,c,d'
54+
)
55+
})
56+
it('throws an error if a digit has multiple matches (meaning a bad codes map)', () => {
57+
expect(
58+
() => decodeSignal(
59+
[['a'], ['d', 'c', 'b'], ['b', 'c', 'd']],
60+
'dcb'
61+
)
62+
).to.throw(
63+
'Too many matches for dcb when cleaned up to b,c,d. This most likely indicates a bad list of character codes.'
64+
)
65+
})
66+
})
67+
})
68+
describe('Part 2', () => {
69+
describe('parseEntry()', () => {
70+
it('parses a set of scrambled codes and signal to produce a number for display', () => {
71+
expect(
72+
parseEntry(
73+
testSingle.split('|').map((x) => x.trim())
74+
)
75+
).to.equal(5353)
76+
77+
const testData = testMultiple.map(
78+
(entry) => entry.split('|')
79+
.map((x) => x.trim())
80+
).map(parseEntry)
81+
82+
expect(testData.reduce((a, b) => a + b)).to.equal(61229)
83+
})
84+
})
85+
})
86+
})

Diff for: 2021/day-08/index.js

+3
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')

Diff for: 2021/day-08/input.txt

+200
Large diffs are not rendered by default.

Diff for: 2021/day-08/solution.js

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
const filePath = path.join(__dirname, 'input.txt')
4+
const { linesToArray } = require('../../2018/inputParser')
5+
const { descrambleSignal, decodeSignal, parseEntry } = require('./display')
6+
7+
fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => {
8+
if (err) throw err
9+
10+
initData = linesToArray(initData.trim())
11+
12+
const resetInput = () => {
13+
// Deep copy to ensure we aren't mutating the original data
14+
return JSON.parse(JSON.stringify(
15+
initData.map(
16+
(line) => line.split('|')
17+
.map((e) => e.trim())
18+
)
19+
))
20+
}
21+
22+
const part1 = () => {
23+
const data = resetInput()
24+
25+
return data.map((entry) => {
26+
const { charCodes } = descrambleSignal(entry[0])
27+
return decodeSignal(charCodes, entry[1])
28+
}).reduce((total, signal) => {
29+
const search = [1, 4, 7, 8]
30+
31+
// Find how many of our desired numbers are in the signal
32+
total += signal.filter((digit) => search.includes(digit)).length
33+
34+
return total
35+
}, 0)
36+
}
37+
38+
const part2 = () => {
39+
const data = resetInput()
40+
41+
return data.map(parseEntry)
42+
.reduce((a, b) => a + b)
43+
}
44+
const answers = []
45+
answers.push(part1())
46+
answers.push(part2())
47+
48+
answers.forEach((ans, idx) => {
49+
console.info(`-- Part ${idx + 1} --`)
50+
console.info(`Answer: ${ans}`)
51+
})
52+
})

Diff for: README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
![](https://img.shields.io/badge/stars%20⭐-14-yellow)
1010
![](https://img.shields.io/badge/days%20completed-7-red)
1111

12-
## Start a boilerplate for a new day
12+
## Run the currently configured default day
13+
`npm start`
14+
15+
### Run in debug mode for extended logging
16+
`DEBUG=1 npm start`
17+
## Generate a boilerplate for a new day
1318
`npm run new`
1419
### Special Instructions
1520
Run by modifying `index.js` to point to the puzzle you want to execute.

Diff for: index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
require('./2021/day-07/solution')
1+
require('./2021/day-08/solution')

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"posttest": "nyc report --reporter=html --reporter=text-lcov > coverage.lcov",
1111
"lint": "standard",
1212
"report-coverage": "codecov",
13-
"new": "npx plop --plopfile ./plop-templates/plopfile.js"
13+
"new": "npx plop --plopfile ./plop-templates/plopfile.js",
14+
"start": "node ./index.js"
1415
},
1516
"repository": {
1617
"type": "git",

0 commit comments

Comments
 (0)