Advent of Code 2020 day 4
My solution for Advent of Code 2020 day 4, this time in Ruby. I have a working Python solution as well, but it’s ugly: Ruby shines with chained methods and blocks.
I have a faint feeling that we’ll be revisiting this passport thing in future challenges…
class Passport
def initialize(attributes)
@attributes = attributes
end
def self.parse_raw_input(raw_input)
raw_input
.strip
.split($/ + $/) # Passports are separated by two newlines in batch file
.map do |passport|
passport
.gsub($/, ' ') # Each passport may be split into multiple lines
end
.map do |passport|
passport
.split # Conveniently, String.split also strips white-space
.to_h do |element|
[
element.split(':').first.to_sym,
element.split(':').last
]
end
end
end
def all_fields_present?
[:byr, :iyr, :eyr, :hgt, :hcl, :ecl, :pid].all? do |f|
@attributes.has_key?(f)
end
end
def all_fields_valid?
return false unless @attributes[:byr].to_i.between?(1920, 2002)
return false unless @attributes[:iyr].to_i.between?(2010, 2020)
return false unless @attributes[:eyr].to_i.between?(2020, 2030)
return false unless (
@attributes.has_key?(:hgt) && (
@attributes[:hgt][-2..] == 'cm' && @attributes[:hgt][0..-3].to_i.between?(150, 193) ||
@attributes[:hgt][-2..] == 'in' && @attributes[:hgt][0..-3].to_i.between?(59, 76)
)
)
return false unless @attributes[:hcl] =~ /^#[\da-f]{6}$/
return false unless ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'].count(@attributes[:ecl]) == 1
return false unless @attributes[:pid] =~ /^\d{9}$/
return true
end
end
def part_one(raw_input)
passports = Passport.parse_raw_input(raw_input).map do |parsed_input|
Passport.new(parsed_input)
end
passports.filter { |p| p.all_fields_present? }.length
end
def part_two(raw_input)
passports = Passport.parse_raw_input(raw_input).map do |parsed_input|
Passport.new(parsed_input)
end
passports.filter { |p| p.all_fields_valid? }.length
end
puts "Part one: #{part_one(IO.read(File.join(__dir__, '../day_04_input.txt')))}"
puts "Part two: #{part_two(IO.read(File.join(__dir__, '../day_04_input.txt')))}"