Advent of Code 2020: Day 2 (Ruby solution)
This time, the tasks are to count valid passwords from a text file.
Each line of text contains two numbers, a letter, and a password. Example input:
1-8 n: dpwpmhknmnlglhjtrbpx
11-12 n: frpknnndpntnncnnnnn
4-8 t: tmttdtnttkr
12-18 v: vvvvvvvqvvvvvqvvgf
3-4 c: cccc
17-18 z: zzzzzzzzdzzzzzzgzr
In the first task, the password is valid if the given letter occurs between the first given number and the second given number of times.
In another task, the password is valid if that letter occurs on exactly one of positions specified by given numbers. If it appears on both positions, the password is invalid though ("exclusive or" operator).
I decided to use a strategy pattern to define two different password policy classes.
class PasswordPolicy
def initialize policy_param_0, policy_param_1, letter
@policy_param_0 = policy_param_0
@policy_param_1 = policy_param_1
@letter = letter
end
end
class FirstPasswordPolicy < PasswordPolicy
def valid? phrase
phrase.scan(/#{@letter}/).size.between?(@policy_param_0, @policy_param_1)
end
end
class SecondPasswordPolicy < PasswordPolicy
def valid? phrase
(phrase[@policy_param_0 - 1] == @letter) ^ (phrase[@policy_param_1 - 1] == @letter)
end
end
def count_valid_passwords file, policy_class
i = 0
file.each_line do |line|
param_0 = line.scan(/\d+/).first.to_i
param_1 = line.scan(/\d+/).last.to_i
letter = line.scan(/[[:alpha:]]/).first
phrase = line.scan(/[[:alpha:]]+/).last
policy = policy_class.new(param_0, param_1, letter)
i += 1 if policy.valid?(phrase)
end
i
end
file = File.read('inputs/day2.txt')
puts count_valid_passwords(file, FirstPasswordPolicy)
puts count_valid_passwords(file, SecondPasswordPolicy)