Extract some code from day 4.

This commit is contained in:
Danila Fedorin 2020-12-04 18:40:10 -08:00
parent 15128fbddf
commit 1a2f18b316
2 changed files with 41 additions and 36 deletions

38
day4.cr
View File

@ -1,20 +1,6 @@
require "./passports.cr"
INPUT = File.read("day4.txt") INPUT = File.read("day4.txt")
def parse_passport(string)
new_hash = {} of String => String
string.split(" ").each do |field|
k,v = field.split(":")
new_hash[k] = v
end
new_hash
end
def parse_passports(lines)
lines.split(/\n\n/).map do |s|
parse_passport(s.chomp.gsub(/\n/, " "))
end
end
def part1 def part1
input = INPUT.clone input = INPUT.clone
passports = parse_passports(input) passports = parse_passports(input)
@ -26,31 +12,11 @@ def part1
puts total puts total
end end
def validate_range(range)
->(s : String) { s.to_i32?.try { |i| range.includes? i } }
end
def validate_regex(regex)
->(s : String) { s.matches?(regex) }
end
def part2 def part2
input = INPUT.clone input = INPUT.clone
passports = parse_passports(input) passports = parse_passports(input)
validators = {
"byr" => validate_range(1920..2002),
"iyr" => validate_range(2010..2020),
"eyr" => validate_range(2020..2030),
"hgt" => ->(s : String) {
return false unless s.match(/^(\d+)(cm|in)$/)
validate_range($~[2] == "cm" ? (150..193) : (59..76)).call($~[1])
},
"hcl" => validate_regex(/^#[0-9a-f]{6}$/),
"ecl" => ->(s : String) { "amb blu brn gry grn hzl oth".split(" ").includes? s },
"pid" => ->(s : String) { s =~ /^[0-9]{9}$/ },
}
total = passports.count do |passport| total = passports.count do |passport|
validators.all? do |k, v| DEFAULT_VALIDATORS.all? do |k, v|
passport[k]?.try { |s| v.call(s) } passport[k]?.try { |s| v.call(s) }
end end
end end

39
passports.cr Normal file
View File

@ -0,0 +1,39 @@
def parse_passport(string)
new_hash = {} of String => String
string.split(" ").each do |field|
k,v = field.split(":")
new_hash[k] = v
end
new_hash
end
def parse_passports(lines)
lines.split(/\n\n/).map do |s|
parse_passport(s.chomp.gsub(/\n/, " "))
end
end
def validate_range(range)
->(s : String) { s.to_i32?.try { |i| range.includes? i } }
end
def validate_regex(regex)
->(s : String) { s.matches?(regex) }
end
def validate_unit_range(unit_ranges)
->(s : String) {
return false unless s.match(/^(\d+)([a-zA-Z]+)$/)
unit_ranges[$~[2]]?.try { |rng| validate_range(rng).call($~[1]) }
}
end
DEFAULT_VALIDATORS = {
"byr" => validate_range(1920..2002),
"iyr" => validate_range(2010..2020),
"eyr" => validate_range(2020..2030),
"hgt" => validate_unit_range({"cm" => (150..193), "in" => (59..76)}),
"hcl" => validate_regex(/^#[0-9a-f]{6}$/),
"ecl" => ->(s : String) { "amb blu brn gry grn hzl oth".split(" ").includes? s },
"pid" => ->(s : String) { s =~ /^[0-9]{9}$/ },
}