Advent of Code 2020: Day 4 (Ruby solution)
Another day, another problem to solve. This time, you are asked for some data validation. You are supposed to parse entries from a text file.
In the first task, only validating the presence of some keys is required. In the second one, you have to check if values meet certain specific constraints:
- byr (Birth Year) - four digits; at least 1920 and at most 2002.
- iyr (Issue Year) - four digits; at least 2010 and at most 2020.
- eyr (Expiration Year) - four digits; at least 2020 and at most 2030.
- hgt (Height) - a number followed by either cm or in: If cm, the number must be at least 150 and at most 193. If in, the number must be at least 59 and at most 76.
- hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f.
- ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth.
- pid (Passport ID) - a nine-digit number, including leading zeroes.
- cid (Country ID) - ignored, missing or not.
REQUIRED_FIELDS = %w(byr iyr eyr hgt hcl ecl pid)
EYE_COLORS = %w(amb blu brn gry grn hzl oth)
def count_valid_entries file, strong_validation = false
valid = 0
file.each_line("\n\n") do |entry|
attrs = Hash[entry.split.map { |key_and_val| key_and_val.split(':') }]
next unless (REQUIRED_FIELDS - attrs.keys).empty?
if strong_validation
next unless attrs['byr'].to_i.between?(1920, 2002)
next unless attrs['iyr'].to_i.between?(2010, 2020)
next unless attrs['eyr'].to_i.between?(2020, 2030)
hgt = attrs['hgt'].scan(/\d+/).first.to_i
if attrs['hgt'].end_with?('cm')
next unless hgt.between?(150, 193)
elsif attrs['hgt'].end_with?('in')
next unless hgt.between?(59, 76)
else next
end
next unless attrs['hcl'].match? /\A#[0-9a-fA-F]{6}\z/
next unless EYE_COLORS.include? attrs['ecl']
next unless attrs['pid'].match? /\A\d{9}\z/
end
valid += 1
end
valid
end
file = File.read('inputs/day4.txt')
puts count_valid_entries(file)
puts count_valid_entries(file, true)