Skip to content

Commit 6357060

Browse files
feat(2020-day-04): scan and validate passport records
1 parent c177121 commit 6357060

File tree

4 files changed

+141
-19
lines changed

4 files changed

+141
-19
lines changed

2020/day-04/passports.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Convert a passport scan into a useable object
2+
const parseScan = (scan) => {
3+
const passport = {}
4+
scan.trim()
5+
.split(/\s+/)
6+
.forEach((field) => {
7+
const parsed = field.split(':')
8+
passport[parsed[0]] = parsed[1]
9+
})
10+
return passport
11+
}
12+
13+
const getType = (passport) => {
14+
if (passport.cid) {
15+
return 'normal'
16+
}
17+
return 'polar'
18+
}
19+
20+
const requiredFields = [
21+
'byr',
22+
'iyr',
23+
'eyr',
24+
'hgt',
25+
'hcl',
26+
'ecl',
27+
'pid',
28+
'cid'
29+
]
30+
31+
const validate = (passport) => {
32+
const fieldsToCheck = JSON.parse(JSON.stringify(requiredFields)) // quick deep copy
33+
// polar records don't have cid, but are otherwise valid
34+
if (getType(passport) === 'polar') {
35+
delete fieldsToCheck.splice([fieldsToCheck.indexOf('cid')], 1)
36+
}
37+
// Check for fields
38+
fieldsToCheck.forEach((field) => {
39+
if (!passport[field]) {
40+
throw new Error(`Missing field ${field}`)
41+
}
42+
})
43+
return true
44+
}
45+
46+
module.exports = {
47+
parseScan,
48+
validate
49+
}

2020/day-04/passports.test.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* eslint-env mocha */
2+
const { expect } = require('chai')
3+
const { parseScan, validate } = require('./passports')
4+
5+
const valid = [
6+
`ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
7+
byr:1937 iyr:2017 cid:147 hgt:183cm`,
8+
`hcl:#ae17e1 iyr:2013
9+
eyr:2024
10+
ecl:brn pid:760753108 byr:1931
11+
hgt:179cm`
12+
]
13+
14+
const invalid = [
15+
`iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
16+
hcl:#cfa07d byr:1929`,
17+
`hcl:#cfa07d eyr:2025 pid:166559648
18+
iyr:2011 ecl:brn hgt:59in`
19+
]
20+
21+
describe('--- Day 4: Passport Processing ---', () => {
22+
describe('Part 1', () => {
23+
describe('parseScan()', () => {
24+
it('parses an individual record into an addressable object', () => {
25+
const res = parseScan(valid[0])
26+
expect(res).to.deep.equal({
27+
ecl: 'gry',
28+
pid: '860033327',
29+
eyr: '2020',
30+
hcl: '#fffffd',
31+
byr: '1937',
32+
iyr: '2017',
33+
cid: '147',
34+
hgt: '183cm'
35+
})
36+
})
37+
})
38+
describe('validate()', () => {
39+
it('verifies all required fields in a passport', () => {
40+
valid.forEach((scan, idx) => {
41+
const passport = parseScan(scan)
42+
// Valid when all required fields
43+
expect(validate(passport)).to.equal(true)
44+
})
45+
})
46+
it('errors on invalid passports', () => {
47+
const passport = parseScan(invalid[0])
48+
expect(() => validate(passport)).to.throw('Missing field hgt')
49+
})
50+
})
51+
})
52+
})

package-lock.json

Lines changed: 37 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,8 @@
3737
"plop": "^2.7.4",
3838
"semantic-release": "^17.3.0",
3939
"standard": "^14.3.4"
40+
},
41+
"dependencies": {
42+
"split2": "^3.2.2"
4043
}
4144
}

0 commit comments

Comments
 (0)