Advent of Code 2020: Day 4 (Ruby solution)

Subscribe to my newsletter and never miss my upcoming articles

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)
Tags:#ruby

No Comments Yet