Skip to content

Commit 29c7a5f

Browse files
feat[2020-day-02]: utilities for formatting and validating passwords
criteria per instructions in part 1
1 parent 093d80c commit 29c7a5f

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

2020/day-02/cleanupPasswords.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Splits a password record into its component parts
3+
*/
4+
const splitRecord = (row) => {
5+
const record = row.split(': ')
6+
.map((el) => el.trim())
7+
8+
return {
9+
rule: record[0],
10+
password: record[1]
11+
}
12+
}
13+
14+
/**
15+
* Splits a password validation rule into its component parts
16+
*/
17+
const splitRule = (rule) => {
18+
const splitRow = rule.split(/-| /)
19+
20+
return {
21+
min: Number(splitRow[0]),
22+
max: Number(splitRow[1]),
23+
char: String(splitRow[2])
24+
}
25+
}
26+
27+
/**
28+
* Validates a password against the specified rule
29+
*/
30+
const isValid = (rule, password) => {
31+
// count how many times `rule.char` exists in `password`
32+
const count = (
33+
password.match(
34+
new RegExp(rule.char, 'g')
35+
) || []
36+
).length
37+
// check the conditions
38+
if (count < rule.min) return false
39+
if (count > rule.max) return false
40+
return true
41+
}
42+
43+
module.exports = {
44+
splitRecord,
45+
splitRule,
46+
isValid
47+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* eslint-env mocha */
2+
const { expect } = require('chai')
3+
const { splitRecord, splitRule, isValid } = require('./cleanupPasswords')
4+
5+
const testData = [
6+
'1-3 a: abcde',
7+
'1-3 b: cdefg',
8+
'2-9 c: ccccccccc'
9+
]
10+
11+
describe('--- Day 2: Password Philosophy ---', () => {
12+
describe('Part 1', () => {
13+
describe('splitRecord()', () => {
14+
it('splits a password record into components parts', () => {
15+
testData.forEach((row, idx) => {
16+
const { rule, password } = splitRecord(row)
17+
expect(`${rule}: ${password}`).to.equal(testData[idx])
18+
})
19+
})
20+
})
21+
describe('splitRule()', () => {
22+
it('splits a password formatting rule into component parts', () => {
23+
testData.forEach((row, idx) => {
24+
const { rule, password } = splitRecord(row)
25+
const { min, max, char } = splitRule(rule)
26+
expect(`${min}-${max} ${char}: ${password}`).to.equal(testData[idx])
27+
})
28+
})
29+
})
30+
describe('isValid()', () => {
31+
it('checks if a specified password matches the specified rule', () => {
32+
const expectedResults = [true, false, true]
33+
testData.forEach((row, idx) => {
34+
const { rule, password } = splitRecord(row)
35+
const { min, max, char } = splitRule(rule)
36+
expect(isValid({ min, max, char }, password))
37+
.to.equal(expectedResults[idx])
38+
})
39+
})
40+
})
41+
})
42+
})

0 commit comments

Comments
 (0)