DEV Community

Discussion on: Advent of Code 2020 Solution Megathread - Day 4: Passport Processing

Collapse
 
sleeplessbyte profile image
Derk-Jan Karrenbeld • Edited

I feel this reads as quite elegant in Ruby -- or at least my implementation of it.

Hoping on something more interesting to do for Day 5!

require 'benchmark'

class Passport
  RULES = {
    byr: -> (value) { /^[0-9]{4}$/.match?(value) && (1920..2002).cover?(value.to_i) },
    iyr: -> (value) { /^[0-9]{4}$/.match?(value) && (2010..2020).cover?(value.to_i) },
    eyr: -> (value) { /^[0-9]{4}$/.match?(value) && (2020..2030).cover?(value.to_i) },
    hgt: -> (value) {
      match = /(^[1-9][0-9]+)(cm|in)$/.match(value)

      match && (
        (match[2] == 'cm' && (150..193).cover?(match[1].to_i)) ||
        (match[2] == 'in' && (59..76).cover?(match[1].to_i))
      )
    },
    hcl: -> (value) { /^\#[0-9a-f]{6}$/.match? value },
    ecl: -> (value) { %w[amb blu brn gry grn hzl oth].include?(value) },
    pid: -> (value) { /^[0-9]{9}$/.match? value }
  }

  def self.from(lines)
    fields = lines.split(' ')

    new(fields.each_with_object({}) do |kv, results|
      k, v = kv.chomp.split(':')
      results[k.to_sym] = v
    end)
  end

  def initialize(fields)
    self.fields = fields
  end

  def [](field)
    fields[field]
  end

  def valid?
    RULES.keys.all? { |field| RULES[field].(self[field]) }
  end

  private

  attr_accessor :fields
end

data = File.read('input.txt')
passports = data
  .split(/\n\n/)
  .map do |l|
    Passport.from(l)
  end

Benchmark.bmbm do |b|
  b.report do
    puts passports.count(&:valid?)
  end
end
Enter fullscreen mode Exit fullscreen mode