Skip to content

Commit

Permalink
Merge pull request #123 from amclin/feat/2020-day-02
Browse files Browse the repository at this point in the history
Feat/2020 day 02
  • Loading branch information
amclin authored Dec 7, 2020
2 parents 2b39e17 + 47c46fa commit 072038c
Show file tree
Hide file tree
Showing 5 changed files with 1,225 additions and 0 deletions.
101 changes: 101 additions & 0 deletions 2020/day-02/cleanupPasswords.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* Splits a password record into its component parts
*/
const splitRecord = (row) => {
const record = row.split(': ')
.map((el) => el.trim())

return {
rule: record[0],
password: record[1]
}
}

/**
* Splits a password validation rule into its component parts
* using the original rules
*/
const oldSplitRule = (rule) => {
const splitRow = rule.split(/-| /)

return {
min: Number(splitRow[0]),
max: Number(splitRow[1]),
char: String(splitRow[2])
}
}

/**
* Splits a password validation rule into its component parts
* using the new rules
*/
const newSplitRule = (rule) => {
const splitRow = rule.split(/-| /)

return {
positions: [
Number(splitRow[0]),
Number(splitRow[1])
],
char: String(splitRow[2])
}
}

/**
* Validates a password against the specified rule
* using the original rules
*/
const oldIsValidPassword = (rule, password) => {
// count how many times `rule.char` exists in `password`
const count = (
password.match(
new RegExp(rule.char, 'g')
) || []
).length
// check the conditions
if (count < rule.min) return false
if (count > rule.max) return false
return true
}

/**
* Validates a password against the specified rule
* using the new rules
*/
const newIsValidPassword = (rule, password) => {
let matches = 0
rule.positions.forEach((pos) => {
// index starts with 1
if (password[pos - 1] === rule.char) {
matches++
}
})
// Only one match allowed, not 2, not 0
return (matches === 1)
}

const oldIsValidRecord = (record) => {
const { rule, password } = splitRecord(record)
const parsedRule = oldSplitRule(rule)
return oldIsValidPassword(parsedRule, password)
}

const newIsValidRecord = (record) => {
const { rule, password } = splitRecord(record)
const parsedRule = newSplitRule(rule)
return newIsValidPassword(parsedRule, password)
}

module.exports = {
old: {
splitRule: oldSplitRule,
isValidPassword: oldIsValidPassword,
isValidRecord: oldIsValidRecord
},
cur: {
splitRule: newSplitRule,
isValidPassword: newIsValidPassword,
isValidRecord: newIsValidRecord
},
splitRecord
}
87 changes: 87 additions & 0 deletions 2020/day-02/cleanupPasswords.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/* eslint-env mocha */
const { expect } = require('chai')
const { splitRecord, old, cur } = require('./cleanupPasswords')

const testData = [
'1-3 a: abcde',
'1-3 b: cdefg',
'2-9 c: ccccccccc'
]

describe('--- Day 2: Password Philosophy ---', () => {
describe('Part 1', () => {
describe('splitRecord()', () => {
it('splits a password record into components parts', () => {
testData.forEach((row, idx) => {
const { rule, password } = splitRecord(row)
expect(`${rule}: ${password}`).to.equal(testData[idx])
})
})
})
describe('splitRule()', () => {
it('splits a password formatting rule into component parts', () => {
testData.forEach((row, idx) => {
const { rule, password } = splitRecord(row)
const { min, max, char } = old.splitRule(rule)
expect(`${min}-${max} ${char}: ${password}`).to.equal(testData[idx])
})
})
})
describe('isValidPassword()', () => {
it('checks if a specified password matches the specified rule', () => {
const expectedResults = [true, false, true]
testData.forEach((row, idx) => {
const { rule, password } = splitRecord(row)
const { min, max, char } = old.splitRule(rule)
expect(old.isValidPassword({ min, max, char }, password))
.to.equal(expectedResults[idx])
})
})
it('won\'t allow more than the specified character count', () => {
const badPass = 'abcabcabcabc'
expect(old.isValidPassword({ min: 2, max: 3, char: 'a' }, badPass))
.to.equal(false)
})
})
describe('isValidRecord()', () => {
it('checks if a specified record contains valid rule and password', () => {
const expectedResults = [true, false, true]
testData.forEach((row, idx) => {
expect(old.isValidRecord(row))
.to.equal(expectedResults[idx])
})
})
})
})
describe('Part 2', () => {
describe('splitRule()', () => {
it('splits a password formatting rule into component parts', () => {
testData.forEach((row, idx) => {
const { rule, password } = splitRecord(row)
const { positions, char } = cur.splitRule(rule)
expect(`${positions.join('-')} ${char}: ${password}`).to.equal(testData[idx])
})
})
})
describe('isValidPassword()', () => {
it('checks if a specified password matches the specified rule', () => {
const expectedResults = [true, false, false]
testData.forEach((row, idx) => {
const { rule, password } = splitRecord(row)
const ruleObj = cur.splitRule(rule)
expect(cur.isValidPassword(ruleObj, password))
.to.equal(expectedResults[idx])
})
})
})
describe('isValidRecord()', () => {
it('checks if a specified record contains valid rule and password', () => {
const expectedResults = [true, false, false]
testData.forEach((row, idx) => {
expect(cur.isValidRecord(row))
.to.equal(expectedResults[idx])
})
})
})
})
})
1 change: 1 addition & 0 deletions 2020/day-02/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./solution')
Loading

0 comments on commit 072038c

Please sign in to comment.