Advent of Code — Day 2
Since its December and Advent of Code is happening, I thought we may as well give a few a go. Today we will look at the day 2, Password Philosophy problem. The passwords in our database have been corrupted and now we must go through these passwords and flag the valid passwords and return how many are valid. The passwords are given to us as strings, the first part will have two numbers separated by a dash and this represents the minimum number of times a certain number should appear and the max number of times that letter should appear. The next piece in our string is the letter we are looking for and lastly separated by a colon and another space is the password string. If this string contains the specific letter N number of times and min <= N <= max, then we will increase our count because the string is valid.
Advent of code gives us our input as one big text file so we will need to account for that in our function. The hardest part of this is really just breaking apart each password string into pieces. We need to keep track of the min and max, the letter we are checking, and the password string. There are numerous ways we could go about breaking apart these strings but regular expression makes our lives very simple. I went at this the hard way at first and then realized I needed to use the right tools! If you’re not familiar with Regex, check out this great learning tool. I will do a brief explanation of the regex we use.
const pattern = /(\d?\d)\-(\d?\d)\s([a-z])\:\s([a-z]*)/gm;
The first thing we see is (\d?\d). The outside parentheses represent a capturing group, this groups multiple tokens together. When we see \d, this matches any digit 0–9. In our situation the number we are checking could either be a single digit or it could be two digits. The question mark (?) after the \d means we will match 0 or 1 of the preceding tokens. Next we look for an additional digit (representing the second number or this represents the single digit, because we did not match on the preceding token).
Next we have \-. This is an escaped character and we ignore the dash in between our digits.
Next is the same as above, checking for one or two digits.
Next \s. This matches any whitespace (spaces, tabs, line breaks)
Next ([a-z]), we create another capture group inside the parentheses. Inside the brackets we see a-z. This creates a character set that we are looking for a match, and this is the range of a-z (charcode 97–122). Also this is case sensitive so we wanted capital letters we would need to do [A-Z].
Next \:, another escaped character, this time a semicolon
Next \s. Again, this matches any whitespace (spaces, tabs, line breaks)
Next ([a-z]*), This is the same as above except we see the asterisk. This is a quantifier and matches 0 or more the preceding token. So it will capture all the letters in our password string.
The exec() method is called on our regular expression and it executes a search for a match in a specified string. It will return a result array if there’s a match or null. This result array will contain a few things.
const pattern = /(\d?\d)\-(\d?\d)\s([a-z])\:\s([a-z]*)/gm
const input = `1–3 a: abcde
matchGroups = pattern.exec(input)
matchGroups = the full string of characters matched (ex. ‘1–3 a: abcde’)
matchGroups,…[n] = the parenthesized substring matches, these are the capture groups from above. (ex. matchGroups = ‘1’, matchGroups = ‘3’, matchGroups = ‘a’, matchGroups = ‘abcde’
Then in the results array comes the index and the input, we don’t need it for our particular problem but if you want to learn more.
So now we have our min, max, the character to find, and the password to check. Now comes the easy part.
We take the password string and filter the string matching the character to find. We take the length of this array and then if min <= length <= max we add 1 to our valid passwords count. The reduce function will return the accumulator with the result.
The second question is slightly different, this time the first two numbers represent indexes, where 1 represents the first character and 2 the second character, and so on. If exactly one of these positions contains the given letter we return true.
We check and see if the first position contains the letter we want to find and we get true or false. We do the same thing for the second position, then we can check to see if positionOne and positionTwo are equal to one (true + true = 2, true + false = 1, false + false = 0) then we know we have found exactly one occurrence and we increase our valid passwords by one.