Skip to content

Commit 135dbf9

Browse files
Merge pull request #208 from amclin/feat/2021-day-10
Feat/2021 day 10
2 parents df3d9fd + de9a7bf commit 135dbf9

File tree

10 files changed

+414
-7
lines changed

10 files changed

+414
-7
lines changed

2021/day-08/display.test.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@ gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce
1818
describe('--- Day 8: Seven Segment Search ---', () => {
1919
describe('Part 1', () => {
2020
describe('descrambleSignal()', () => {
21-
const testData = testSingle.split('|')[0].trim()
22-
const { segmentCodes, charCodes } = descrambleSignal(testData)
23-
2421
it('takes scambled string of 10 codes and identifies the letters matching each seven-digit-display segment', () => {
22+
const testData = testSingle.split('|')[0].trim()
23+
const { segmentCodes } = descrambleSignal(testData)
2524
expect(segmentCodes.length).to.equal(7)
2625
expect(segmentCodes.filter((code) => !['a', 'b', 'c', 'd', 'e', 'f', 'g'].includes(code)).length).to.equal(0)
2726
})
2827

2928
it('produces a list of character codes for each number that can be displayed', () => {
29+
const testData = testSingle.split('|')[0].trim()
30+
const { charCodes } = descrambleSignal(testData)
3031
// There should be exactly 10 numbers
3132
expect(charCodes.length).to.equal(10)
3233
// lengths of each code is predictable as each number has a specific count of segments
@@ -35,10 +36,9 @@ describe('--- Day 8: Seven Segment Search ---', () => {
3536
})
3637
})
3738
describe('decodeSignal()', () => {
38-
const testData = testMultiple[0].split('|').map((a) => a.trim())
39-
const { charCodes } = descrambleSignal(testData[0])
40-
4139
it('decodes a display pattern using the provided map of display codes', () => {
40+
const testData = testMultiple[0].split('|').map((a) => a.trim())
41+
const { charCodes } = descrambleSignal(testData[0])
4242
const result = decodeSignal(charCodes, testData[1])
4343
expect(result[0]).to.equal(8)
4444
expect(result[3]).to.equal(4)

2021/day-10/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')

2021/day-10/input.txt

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
[[<[<{[<{{<[{(()[])[[]()]}[((){})<[]{}>]}<<{[]{}}<(){}>><([]<>)>>>[[[<<>>[<><>]][<<>>(<><>)]][{
2+
((<[(<<(<{<((<()<>>{()()}){<<>><()[]>})([{<>{}}(()[])]{(<><>>})>(<((()())<[][]>)>([(<>{})({}())][<
3+
<<<(<<[[((({<([]<>)[[]]>{<{}>{(){}}}}{[<[][]><<>[]>]({<><>}{()<>})})[<<({}())(()<>)>[([]{})<[]()>]>({[[]
4+
<(<<<[((([{({((){})<<>{}>}[<(){}>[<>()]])[[<{}[]>({}{}]](<<>[]><[]<>>)]}](<[({[][]}<()<>>)<[
5+
{<<<{[({{(<<(<<>[]><[]()>){<[][]>{<>{}}}>((({}())([]<>))[<{}{}>({}())])>(<<<()[]>><<<>{}>(()<
6+
{<{<<[[(<<[{<<{}[]>>([<>()]{{}{}})}]<(<{<>()}{{}()}>{({}[])<<>()>})>>>){[{[{<[[]{}][<><>]>}{(<{}(
7+
(((([(({((<[<(<>{})[{}{}]>](<[()<>]{<><>}>)><<[<[]{}>((){})]<[()[]]>>{[{<>()}((){})]({()[]}(()[]))}>))}(
8+
<<[(({({(<{{((<>[])[[]<>])([<>]{()()})}<<{<>[]}><<{}()>>>}>)(<(<{<()[]><(){}>}{{(){}}[{}<>]}>{
9+
(([[{<[<<{[<{<()[]>{<>[]}}{<{}{}>{[]<>}}>[{<{}{}>(<>[])}]]{<<({}[])>(<[]<>>[{}])>({{<>()}(<
10+
(<{{(<<{[([<<{()[]}>{({}<>){<>[]}]>((<[]{}><{}{}>))]([{(()<>)(<>[])}]<<((){})<<>{}>>[(()[])
11+
{{[[<<{<{{{([{()[]}[{}()]]{(<>{}){<><>}}){<[[][]][()[]]>}}<{{<[][]>[{}[]]>(<<>{}><{}{}>)}>}}<<{[{([](
12+
{[<({{{[<{<{[([][])]{({}())<[][]>}}((<(){}>{()<>})<<<>{}>>)>}(((<{<>{}}<{}()>>)[((()()))[<<>{}>(
13+
{{{[{{[(([{{[[{}<>]([]<>)]([(){}][[]()])}[{{[]<>}[{}()]}(<<><>>]]}][[([[[]<>]<<>{}>][{[]{}
14+
<<{{{[{{[<({<<[]<>><{}<>>>}[[{()<>}{[]<>}]({(){}}{{}()})])[[(<<>[]>[[]])[{{}{}}[[]()]]]<((
15+
({{[{{{{<[[({[{}{}]{[]<>}}<<()<>>(()<>)>)<{{(){}]<()()>}{{(){}}[<><>]}>]<<({{}{}}<(){}>)([{}
16+
{([[[<<([[{{[<()<>>(()<>))({<>[]}(<>{}))}{(<{}()>{()[]})}}([[{{}[]}<[]>]<([]<>){<>}>])]<{[[([]{})]{(<><>)[[]<
17+
([<<([<[[({((({}[]){[]{}}){({}[])({}<>)})>)[(<{{{}{}}[(){}]}(([][])<{}<>>)><[[<><>]{<>{}}]{{{}[]}{[][]}}>)<[[
18+
{[<<{[<{[<{[[({}[])({}<>)]<<{}{}>{{}()}}]{[[<>{}]<[]{}>]}}(([(<><>){[][]}]([<>()]<()[]>))<[<()<>>(<><>)
19+
(<[<[(({{<{<<[{}()]>(([]())<<>[]>)>}[{<[[]{}]([]<>)><{<><>}[()<>]>}{{{(){}}{[]{}}}}]>}}){{<{([<([]())({}())
20+
<<{({{<[<[{([{{}<>}{<><>}]([(){}](()[]))){[{()[]}<<>()>]({()()}({}()))}}]<[<<(())(()[])>>{(<{}<>>{
21+
{{{(<<[(<[([[[()<>]<()[]>]]{[[[]{}]{<>{}}]((<><>)({}{}))})]([(<{<>()}{[]{}}><<{}{}><<>[]>>)[<<()[]>((){
22+
[{(<<{[<<([{[<[][]>][{()()}({}())]}]([{([]{})<{}<>>}(<()>[{}])]{<([]<>)<{}{}>>(({}<>)<<><>>)}))>([[((<<>{}
23+
[[(<({{(({{(<[{}<>]([]{})>{[<>[]]([][])})[(<[]<>><{}()>)[<{}()>(())]]}<[<[[]{}]<{}{}>>{<()()>({}<>)}]<
24+
([(<({(<{{(((<[]<>>{<>()})<{[]{}>([]{})>)[<[()<>]({}[])>[(<>{})(<>[])]]){<((<>{}){()[]})><{<[]<>><<><>>
25+
({{<({(<<({[[{<><>}]<<<><>>({}[])>]([<[]<>>[{}()]]{{<>{}}({}[])}}}<{({[]<>}({}{}))[(<>())(<>())]}((([]{}){[][
26+
(((({[(<([<[(<<>>[[][]])<{<><>}[{}<>]>]{({<>()}(<><>))(({}<>))}>])<([[<<()<>>{[][]}>]<[[[][
27+
[<<(([({((<<{({}())}[(()()){[]<>}]>>){({<[{}{}]<<>()>>{<{}()>}})})})])[[<((<[{([<>()][{}[]])((()[])
28+
{{{<{[[(<[{{<<{}()>[{}<>]>{({}{})<()>}}(<[(){}]>(<(){}>[[]]))}(<<[[]{}}({})><[<>[]]{<><>}>><[<[]<>>{<><>}](((
29+
{<[[<[{{<((<[<<>()><[]{}>][<{}()><{}{}>]>)[[[[[][]]<()[]}][([]{})(()())]]])>[[((<{[]<>}<()>><[{}[]](<><>)>
30+
<{([{[{[{([({<{}[]>([]<>)}[[[][]]<()()>])[<[{}()]>{<<><>>(()<>)}]]){({(<[]<>>([]<>))[(<>){
31+
[{{<(({<{[{<{({})(<>[])}({<><>}{[]()})>(({[]<>}(<>{}))[{()()}{{}<>}])}{<{{<>()}<[]{})}(<()><(
32+
{(<[{[[{{<(([{{}{}}<()[]>]<[<><>]>)([(<><>)])){<<{[]{}}[[][]]>{[[]<>]{<>{}}}>[<<[][]><<>()>><<{}<>>[<>()>>]}>
33+
<[{{(<<{{{[[{<[]<>>(()<>)}<{()<>}{<>[]}>]<[<()()>]{<<>>([]())}>]{([<<>{}>({}<>)])[({{}}{[]<>})[
34+
<<[[<<[(<{{{[{()[]}([]())][[[]]((){})]}}(([{[][]}[()()]]<<()>[{}[]]>))}>)<{({{<[[][]]{()()}><<{}{}
35+
{[<(([([{({([({}()){<><>}][((){})([]())])[<<()<>>(<>())>{[[]()}(()[])}]}<{{<(){}>{()[]}}((<><>){{}<>})}((
36+
{(({([[{{((([<()()>([][])]<<{}[]>[<>]>)(<{<><>}[{}{}]>[[<>{}]]))[{<<[][]>[()]><[{}{}]>}{<([]<>)([]<>)>}]
37+
(({[[<<<{[{([(<>[])<()[]>])(<([])({}{})>)}[{(<<>{}>({}<>))}<<[<>[]>[(){}]>(<{}{}>)>]]{([[<<>()>
38+
[{[[{([({[{(({()[]}[[]<>])<[[]<>]([])>)([{{}{}}[{}[]]]<{{}<>}>)][<(<<>[]>{<><>})<(()<>){[][]}>>[[{[]{}}([]())
39+
([[{({([({<<(<[]<>>)[{()[]}<<>()>]><<{<>()}<<>[]>>[[<>{}]<<><>>]>)<<<<<>[]><<><>>>[[[]]]>[{
40+
[{{([(<[[<{((([]{})[()()])[<[]{}>[<>()]])<[{()()}(<>{})]({[]}[<>{}])>}((<{[]()}>)({<{}{}>[
41+
[[[{{[[[<<(<(({}())[<>{}])<{{}<>}(()())>>[[((){})][[[]{}]{()}]])>>{[(<([{}{}]({}<>))([{}()]<<>[]])>({<
42+
{<{({(({{{[{<(<>{})>{<{}<>>(<><>)}}<(<[]()>[[][]])<[{}()]>>]<{{<()[]>{{}()}}{<{}[]>{{}{}}}}{{<()<>><<>
43+
[{[<{[<<({(<{{<>()}({}<>)}<(<>[])[()()]>>{{{<>()}{()[]}}})<{<({}()){<>{}}>({<>[]}({}())]}>}(
44+
[[{<([((({([{{()[]}<[]{}>}({<>[]}[<><>])]{{<[]<>>[<><>]}[{()()}[<>[]]]})}[{[<{()()}(<>))<({}){()<>}>]([
45+
(<(<{[{<({[{{{[]()}({}{})}{<{}[]><<>{}>}}]})>}<{[[(<[<[]{}>([]())](<{}>[()()])>)][(([{[]<>
46+
<<<<{<{<<[<({<[]>({}<>)})<[{[][]}[[]()]][[{}<>]<{}[]>])>([(([][])[[]()])<[{}[]]{[]{}}>](<[{}()]{{}()}
47+
({[[([([<{[[({()[]}[<>[]])[<[][]><<>{}>>][(({}{})(<>[])){(<>[])}]]<{{{{}()}[<>[]]}<[[]<>]([]())>}>}{<{({
48+
((<{<{{[((<<<(()<>)<[]{}>>[<[][]>[(){}]]>>)){([[[[<>]({}<>)]{{{}<>}([]{})}]<[<<>()>(()())][{[]{}}{[]<>}]>]
49+
{<<{{[({[<{{(<{}[]><<>[]>)([[]()])}<[{{}{}}{<><>}]<({})<{}()>>>}<[([{}<>][<>{}])](<<{}[]><<
50+
{[{[[<<[(({[(((){}){<>[]})]([[<>[]]][<<>{}>[<><>]])})({<[({}[])<{}[]>]>}<(<(()<>)[[]{}]][[()()][<><
51+
((<<[({<{[[({<[]()>([]())}[<[]{}>(()<>)])]<<{[{}[]][<>()]}><<{<>[]}[()<>]>[<[]{}>{[]()}]>>][(({[<>
52+
{{<[{<([({{([<<><>>{{}()}][<[][]>{[]()}])[<[[]]{[]<>}>]}(({<()[]>[{}()]}<[[]<>]{<>()}>))})])<{[{<[<[{}{}]
53+
[(({({[[<{(<{{<>[]}[()<>]}((<>{})<<>[]>)>{[<(){}>{{}<>}]])[<{(<>[]){{}[]}}([()()][<>[]])>((({}())
54+
{(([<{([[{([<<{}()><[][]>>[(<>()){()[]}]]<[<()()>[{}]]([{}<>][{}[]])>){<{[[]<>]<<>{}>}{([]{})}>[([
55+
<{[{({([(<<{<[()<>]<(){}>>(<()>{[][]})})>{[([<{}{}>[<>()]])[{([]()){<>{}}}<<{}<>>>]]})])([<(([{<(){}>[{
56+
<<<(([<[{[[<{({}()>{[]()}}>]]([<[[()][{}[]]]<[()()]{(){}}>><<({}[])(()<>)>{(()[])}>]{[(<[]()>)[{[]{}}
57+
(({(([[<{(<{[(<>[]]]}<(({}{}))([[][]]([][]))>><[{(()())[()<>]}<{(){}}>]>)((<{{()[]}{<>()}}<([
58+
[[[{<[{<[<[[{(<>{})<[]()>}{(()[])[<>()]}][<({}()>[<><>]>{<[]{}><[][]>}]]><<{[{(){}}{{}{}}][<<><
59+
((([<<((<[{(([<>[]]([]{}))([<>]{<>()})}([[(){}][[]()]][(<><>){{}()}])}{[<[()<>]({}<>)>[<{}{}>]][<(<>())<[]
60+
{<<{([(((([{<[()]{(){}}>{{{}[]}}}[{(()[]){()<>}}{<<>>[<>{}]}]]<[{(<>())(()[])}]>){[[<({}{})[()[]]>{[{}(
61+
([{(({([([(<<{<>[]}<{}<>>>[[[]{}]<[]{}>]>((([]<>)<<>[]>)[[(){}]]))[<{{<>{}}}[(<>}{()()}]><{<<>{}><
62+
{(<[<{({([{{([[][]]>({()()}[[][]])}[<(()())([]())><(<><>)([]{})>]}[(({{}{}}{{}<>})([<><>]<()[]>))]
63+
((<(<<{{{{<{{(()<>)({}{})}{{<>[]}<()[]>}}<<<[][]>(()[])>[[()[]][[]()]]>>[[{{[]{}}[[][]]}][<[()[]]{[]<>}>
64+
(((<(<<<{{<{<{{}{}}(()<>)>[((){})[()[]]]}{[[<>[]]{{}()}][{()[]}({}{})]}>}}>{[{<<{[{}()]}<[[]()]
65+
({(([[<{[{<(([[]()](<><>))[<{}[]){{}()}])(<[()[]]<[]()>>[<{}<>>[()<>]])>[<[[()()]<<>[]>][([]())([]{})]>{{<<>(
66+
[[(([((([<[[<{{}<>}({}[])>[([]<>)[()[]]]]<[(()())({}<>)](([]<>)<[]()>)>]>[{{{(()<>)}<{[]()}
67+
(<(({[<<{((<[[[]()]{{}<>}]<<{}()>({}[])>>)<{{({}){()()}}<{[][]}>}>){[(<<[]<>>[{}{}]>{{(){}}{[
68+
{<(<(<<{<(<{{[{}[]]([]{})}([{}[]](<>))}[([<>()]{[]{}})<({}<>){<><>}>]>[{<[[][]]>}[<[<><>](()())>(([
69+
{(<(<{<(<<{{{<(){}>}({[][]}{{}{}})}}<(<<<>()>[(){}]>(<{}()>{{}}))>>[{{[{[]{}}(()[])]}[((<>())<<
70+
([((([[{([{<<((){})>{{<>}{[]()}}>{[((){})<()[]>]<{[]{}}[(){}]>}}{((<{}()><{}>)){{<{}[]>[[]
71+
{{{(<<{((([[{(<>{})({}())}[<[]()>({}{})]]<<[{}]>{[[]()]{()[]}}>]{({<()[]>((){})})<{<[]<>>{{}{}
72+
(<<[[([{{(<<({{}}[{}{}])<([]{}){<>()}>>>(({<()()>({}[])}<<{}()>[(){}]>)))[{([{<>[]}([]())]([()()][<>{}])){
73+
<(<(<<<([[[(<{{}[]}{{}[]}>[[<>()]{()[]}])]<{({{}()}{{}<>})<({}[])([]<>)>}{(({}[])(<>{}))((()<>)<[]()>)}>](<
74+
<<{(([<([[[[<{<>()}({}[])>{((){})[{}()]}]}[<{<<>[]><[]<>>}<[{}<>]{{}()}>>{{(()())[()[]]}{<()<>
75+
(({<<[{([{<(([{}[]][(){}])[<[]()>(()<>)]}>}<[(<{{}()}{{}<>}><[[]()][[]()]>)]<(<(<>())>({<>[]})){[{(){}}<{}{}>
76+
({[[{[{{<(([[[{}{}]<(){}>]((()[])(()[]))]({([]<>)({}{})}{<<>{}>{<>}}))<{(<[]{}>(()()))[[()[]](<><>)
77+
([{[{{<{{(<[((<>){[]()})(({}())[<><>])]>({[(<><>}{{}[]}]{(()[])[()]}}{([[]{}](<><>))<<{}[]>(<>())>}))
78+
<[(([[[<{[[(({()[]}<<>[]>){{<><>}<(){}>})<([()]{<>[]}){{<>{}}}>]]<[{{([]())({}{}>}<{[][]}<<>{}>
79+
({(<{<([[<{[<{[]()}[{}<>>>[[(){}][[]{}]]][{[()<>][<><>]}{<()()>}]}<({{(){}}<()()>}{[<><>](<>())})[(
80+
([({<[<[{({<<[<>{})[<><>]>{{[]{}}}>[[{()<>}([]{})](({}<>)<<>>)]}<{<<<>>{()[]}>}<{<[]()>}>>)(<<<{
81+
({<{[[({[([{[{[]{}}{[]<>}](((){})({}()))}]([<{<>{}}{()<>}>{({}{})(()())}])}]<{({{<()[]>{()}}
82+
({[[{[((<[[[{<<>[]>(<>[])}]]{<({{}[]}){[{}{}]<<>()>}>[([<>()]{{}()})(<()()><<>[]>)]}]>(<([{<[]{}>(()())}<{[
83+
[<<<{<({({{<{[<><>]{{}<>}}{<(){}>}>}})})[<<[{[{({}{})<<>>}[{[]}(()())]]{{([]())([]())}{({}[])[<>
84+
<<<[[((<{{<(((<>[])(()))<<<>()><<>{}>>)<[{<>[]}{(){}}]{[{}]({}())}>>}}[[((({()}{[][]}){<{}[]>}
85+
(<[<({[[{[<<[(<>[])]([[]<>]<[]{}>)>({(<>[])([]())}<[{}<>)<<>{}>>)>[{<[[][]]><[{}<>]<[]()>>}<<[
86+
{[({<<<<(<([{{[][]}}]{<{<>()}<<>()>>[({}())<[]{}>]})>)>>><<<{{((([{}[]]<<><>>)[[[][]]({}[])])<{<{}{}>(
87+
[[[({((({<([({[][]}{[]})<({}[]}[{}{}]>][([[]()]([]()))<<()<>>>])<[<<()[]><()[]>>]>>([<<{[]()}{[][]}><
88+
[{{<<<({<({(<<<><>>>{(<>[])[<><>]})<(<<>{}>(()()))[{{}()}{(){}}]}}[(<{[]()}<[]<>>>({<>{}}[{}
89+
([<<{<[{([<[<{<>{}}<[]{}>><([][]>>][{([][])[()()]}<<[]<>>>]>][{<({<>()}<[][]>)[[[]<>]{()<>}
90+
({<<[<(<<<(<((()<>)<{}<>>)>)<<([<>{}][<>[]])<<()()>({}[])>>([(()())(()<>)]{{{}<>}<[]{}>})>>>>[
91+
<{[{<[[<[(<{({<><>}{[]<>}){<[]{}><()>}}({({})[[]{}]})>{(<{[]<>}{<><>}>([{}[]]{<><>}))(<<{}()>[
92+
<{{<[[({{{<({<[]()>[{}[]]}<{<><>}{()<>}>)[<<[]{}>{{}<>}>[<<>[]>((){})]]>}}(<[[(([][])[{}<>]){(()<>)[()[]]}]((
93+
[{[{<[(({{({<{{}{}}<()()>>(<[]<>>{<>[]})}(<<()[]>{()<>}>))<<<[{}{}]<<>[]>>>[[{[]{}}]((()<>){<>
94+
{[[<{({[<(<((<{}[]>){[{}[]]})[{[{}{}]({}())}]>(<{{()<>}(<><>)}[(<><>)<[]{}]]><{<()[]>([][])

2021/day-10/linting.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const pairs = {
2+
'(': ')',
3+
'[': ']',
4+
'{': '}',
5+
'<': '>'
6+
}
7+
8+
const lintLine = (line) => {
9+
let expected = ''
10+
let pos = 0
11+
while (pos < line.length) {
12+
const char = line[pos]
13+
14+
// if opening bracket, add mate to the start of expected list
15+
if (pairs[char]) {
16+
expected += pairs[char]
17+
} else { // if closing bracket
18+
// if expected closing, clear from the expected list
19+
if (expected[expected.length - 1] === char) {
20+
expected = expected.slice(0, -1)
21+
} else { // otherwise, found an error to report
22+
return {
23+
char: pos,
24+
expected: expected[expected.length - 1],
25+
found: char
26+
}
27+
}
28+
}
29+
30+
pos++
31+
}
32+
33+
// if we run out of characters in the line, that means it is
34+
// incomplete, and we need to provide an autocomplete suggestion
35+
if (expected.length > 0) {
36+
// Reversing the 'expected' string gives us the autocomplete suggestion
37+
return {
38+
suggestion: [...expected].reverse().join('')
39+
}
40+
}
41+
}
42+
43+
const lintAll = (instructions) => {
44+
const errors = instructions.map(lintLine) // lint each line
45+
.map((error, idx) => {
46+
return { ...error, line: idx }
47+
}).filter((report) => !!(report.char) || !!(report.suggestion)) // remove lines without errors
48+
49+
console.log(`Linting found ${errors.length} errors in ${instructions.length} lines.`)
50+
// console.debug(instructions)
51+
// console.debug(errors)
52+
53+
return errors
54+
}
55+
56+
module.exports = {
57+
lintLine,
58+
lintAll
59+
}

2021/day-10/linting.test.js

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/* eslint-env mocha */
2+
const { expect } = require('chai')
3+
const { lintLine, lintAll } = require('./linting')
4+
5+
const badChunks = [
6+
'(]',
7+
'{()()()>',
8+
'(((()))}',
9+
'<([]){()}[{}])'
10+
]
11+
12+
const testData = `[({(<(())[]>[[{[]{<()<>>
13+
[(()[<>])]({[<{<<[]>>(
14+
{([(<{}[<>[]}>{[]{[(<()>
15+
(((({<>}<{<{<>}{[]{[]{}
16+
[[<[([]))<([[{}[[()]]]
17+
[{[{({}]{}}([{[{{{}}([]
18+
{<[[]]>}<{[{[{[]{()[[[]
19+
[<(<(<(<{}))><([]([]()
20+
<{([([[(<>()){}]>(<<{{
21+
<{([{{}}[<[[[<>{}]]]>[]]`
22+
23+
const autocomplete = {
24+
'[({(<(())[]>[[{[]{<()<>>': '}}]])})]',
25+
'[(()[<>])]({[<{<<[]>>(': ')}>]})',
26+
'(((({<>}<{<{<>}{[]{[]{}': '}}>}>))))',
27+
'{<[[]]>}<{[{[{[]{()[[[]': ']]}}]}]}>',
28+
'<{([{{}}[<[[[<>{}]]]>[]]': '])}>'
29+
}
30+
31+
describe('--- Day 10: Syntax Scoring ---', () => {
32+
describe('Part 1', () => {
33+
describe('lintLine()', () => {
34+
it('finds instnces of closing brackets that mismatch the opening brackets', () => {
35+
expect(lintLine(badChunks[0])).to.deep.equal(
36+
{
37+
char: 1,
38+
expected: ')',
39+
found: ']'
40+
}
41+
)
42+
expect(lintLine(badChunks[1])).to.deep.equal(
43+
{
44+
char: 7,
45+
expected: '}',
46+
found: '>'
47+
}
48+
)
49+
expect(lintLine(badChunks[2])).to.deep.equal(
50+
{
51+
char: 7,
52+
expected: ')',
53+
found: '}'
54+
}
55+
)
56+
expect(lintLine(badChunks[3])).to.deep.equal(
57+
{
58+
char: 13,
59+
expected: '>',
60+
found: ')'
61+
}
62+
)
63+
})
64+
})
65+
describe('lintAll', () => {
66+
it('finds all lines with linting errors', () => {
67+
const errors = lintAll(testData.split('\n'))
68+
.filter((err) => (err.char))
69+
70+
expect(errors.length).to.equal(5)
71+
expect(errors[0]).to.deep.equal({
72+
line: 2,
73+
char: 12,
74+
expected: ']',
75+
found: '}'
76+
})
77+
expect(errors[1]).to.deep.equal({
78+
line: 4,
79+
char: 8,
80+
expected: ']',
81+
found: ')'
82+
})
83+
expect(errors[2]).to.deep.equal({
84+
line: 5,
85+
char: 7,
86+
expected: ')',
87+
found: ']'
88+
})
89+
expect(errors[3]).to.deep.equal({
90+
line: 7,
91+
char: 10,
92+
expected: '>',
93+
found: ')'
94+
})
95+
expect(errors[4]).to.deep.equal({
96+
line: 8,
97+
char: 16,
98+
expected: ']',
99+
found: '>'
100+
})
101+
})
102+
it('provides autocomplete suggestions for incomplete lines', () => {
103+
const data = testData.split('\n')
104+
const errors = lintAll(data)
105+
.filter((err) => !!err.suggestion)
106+
107+
expect(errors.length).to.equal(5)
108+
errors.forEach((err) => {
109+
expect(err.suggestion).to.equal(
110+
autocomplete[data[err.line]]
111+
)
112+
})
113+
})
114+
it('skips lines without errors', () => {
115+
const errors = lintAll([
116+
'[]',
117+
'[()]'
118+
])
119+
expect(errors.length).to.equal(0)
120+
})
121+
})
122+
})
123+
})

2021/day-10/scoring.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
const findMiddleScore = (scores) => {
3+
// According to specs, there's always an odd number of items in the list,
4+
// so we're safe to divide by 2 and round down to get the desired index
5+
return scores.sort((a, b) => a - b)[
6+
Math.floor(scores.length / 2)
7+
]
8+
}
9+
10+
// How many points each character is worth in autocomplete scoring
11+
const pointValues = {
12+
')': 1,
13+
']': 2,
14+
'}': 3,
15+
'>': 4
16+
}
17+
18+
const scoreAutocomplete = (suggestion) => {
19+
return [...suggestion].reduce((score, char) => {
20+
return (score * 5) + pointValues[char]
21+
}, 0)
22+
}
23+
24+
module.exports = {
25+
findMiddleScore,
26+
scoreAutocomplete
27+
}

2021/day-10/scoring.test.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* eslint-env mocha */
2+
const { expect } = require('chai')
3+
const { findMiddleScore, scoreAutocomplete } = require('./scoring')
4+
5+
const scoreData = [
6+
288957,
7+
5566,
8+
1480781,
9+
995444,
10+
294
11+
]
12+
13+
const autocompleteSuggestions = [
14+
'}}]])})]',
15+
')}>]})',
16+
'}}>}>))))',
17+
']]}}]}]}>',
18+
'])}>'
19+
]
20+
21+
describe('--- Day 10: Syntax Scoring ---', () => {
22+
describe('Part 2', () => {
23+
describe('scoreAutocomplete()', () => {
24+
it('takes a single autocomplete suggestion and scores it', () => {
25+
autocompleteSuggestions.forEach((suggestion, idx) => {
26+
expect(scoreAutocomplete(suggestion)).to.equal(scoreData[idx])
27+
})
28+
})
29+
})
30+
describe('findMiddleScore()', () => {
31+
it('takes a list of scores and returns the middle entry after sorting', () => {
32+
expect(findMiddleScore(scoreData)).to.equal(288957)
33+
})
34+
})
35+
})
36+
})

0 commit comments

Comments
 (0)