Skip to content

Feat/2021 day 08 #206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Dec 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
469 changes: 469 additions & 0 deletions 2021/day-08/display.js

Large diffs are not rendered by default.

86 changes: 86 additions & 0 deletions 2021/day-08/display.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* eslint-env mocha */
const { expect } = require('chai')
const { descrambleSignal, decodeSignal, parseEntry } = require('./display')

const testSingle = 'acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf'

const testMultiple = `be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce`.split('\n')

describe('--- Day 8: Seven Segment Search ---', () => {
describe('Part 1', () => {
describe('descrambleSignal()', () => {
const testData = testSingle.split('|')[0].trim()
const { segmentCodes, charCodes } = descrambleSignal(testData)

it('takes scambled string of 10 codes and identifies the letters matching each seven-digit-display segment', () => {
expect(segmentCodes.length).to.equal(7)
expect(segmentCodes.filter((code) => !['a', 'b', 'c', 'd', 'e', 'f', 'g'].includes(code)).length).to.equal(0)
})

it('produces a list of character codes for each number that can be displayed', () => {
// There should be exactly 10 numbers
expect(charCodes.length).to.equal(10)
// lengths of each code is predictable as each number has a specific count of segments
const expectedLengths = [6, 2, 5, 5, 4, 5, 6, 3, 7, 6]
expect(charCodes.map(code => code.length)).to.deep.equal(expectedLengths)
})
})
describe('decodeSignal()', () => {
const testData = testMultiple[0].split('|').map((a) => a.trim())
const { charCodes } = descrambleSignal(testData[0])

it('decodes a display pattern using the provided map of display codes', () => {
const result = decodeSignal(charCodes, testData[1])
expect(result[0]).to.equal(8)
expect(result[3]).to.equal(4)
})
it('throws an error if a digit doesn`t have a matching code', () => {
expect(
() => decodeSignal(
[['a']],
'dcb'
)
).to.throw(
'No match found for dcb when cleaned up to b,c,d'
)
})
it('throws an error if a digit has multiple matches (meaning a bad codes map)', () => {
expect(
() => decodeSignal(
[['a'], ['d', 'c', 'b'], ['b', 'c', 'd']],
'dcb'
)
).to.throw(
'Too many matches for dcb when cleaned up to b,c,d. This most likely indicates a bad list of character codes.'
)
})
})
})
describe('Part 2', () => {
describe('parseEntry()', () => {
it('parses a set of scrambled codes and signal to produce a number for display', () => {
expect(
parseEntry(
testSingle.split('|').map((x) => x.trim())
)
).to.equal(5353)

const testData = testMultiple.map(
(entry) => entry.split('|')
.map((x) => x.trim())
).map(parseEntry)

expect(testData.reduce((a, b) => a + b)).to.equal(61229)
})
})
})
})
3 changes: 3 additions & 0 deletions 2021/day-08/index.js
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')
200 changes: 200 additions & 0 deletions 2021/day-08/input.txt

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions 2021/day-08/solution.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const fs = require('fs')
const path = require('path')
const filePath = path.join(__dirname, 'input.txt')
const { linesToArray } = require('../../2018/inputParser')
const { descrambleSignal, decodeSignal, parseEntry } = require('./display')

fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => {
if (err) throw err

initData = linesToArray(initData.trim())

const resetInput = () => {
// Deep copy to ensure we aren't mutating the original data
return JSON.parse(JSON.stringify(
initData.map(
(line) => line.split('|')
.map((e) => e.trim())
)
))
}

const part1 = () => {
const data = resetInput()

return data.map((entry) => {
const { charCodes } = descrambleSignal(entry[0])
return decodeSignal(charCodes, entry[1])
}).reduce((total, signal) => {
const search = [1, 4, 7, 8]

// Find how many of our desired numbers are in the signal
total += signal.filter((digit) => search.includes(digit)).length

return total
}, 0)
}

const part2 = () => {
const data = resetInput()

return data.map(parseEntry)
.reduce((a, b) => a + b)
}
const answers = []
answers.push(part1())
answers.push(part2())

answers.forEach((ans, idx) => {
console.info(`-- Part ${idx + 1} --`)
console.info(`Answer: ${ans}`)
})
})
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
![](https://img.shields.io/badge/stars%20⭐-14-yellow)
![](https://img.shields.io/badge/days%20completed-7-red)

## Start a boilerplate for a new day
## Run the currently configured default day
`npm start`

### Run in debug mode for extended logging
`DEBUG=1 npm start`
## Generate a boilerplate for a new day
`npm run new`
### Special Instructions
Run by modifying `index.js` to point to the puzzle you want to execute.
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
require('./2021/day-07/solution')
require('./2021/day-08/solution')
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"posttest": "nyc report --reporter=html --reporter=text-lcov > coverage.lcov",
"lint": "standard",
"report-coverage": "codecov",
"new": "npx plop --plopfile ./plop-templates/plopfile.js"
"new": "npx plop --plopfile ./plop-templates/plopfile.js",
"start": "node ./index.js"
},
"repository": {
"type": "git",
Expand Down