Add cleaned up day 4 solution.

This commit is contained in:
Danila Fedorin 2020-12-03 23:52:28 -08:00
parent 2ed1ce8b06
commit 15128fbddf

69
day4.cr
View File

@ -1,4 +1,4 @@
INPUT = File.read("day4.txt").lines.map(&.chomp) INPUT = File.read("day4.txt")
def parse_passport(string) def parse_passport(string)
new_hash = {} of String => String new_hash = {} of String => String
@ -10,19 +10,9 @@ def parse_passport(string)
end end
def parse_passports(lines) def parse_passports(lines)
passports = [] of Hash(String, String) lines.split(/\n\n/).map do |s|
passport = [] of String parse_passport(s.chomp.gsub(/\n/, " "))
lines.each do |line|
unless line.empty?
passport << line
next
end end
passports << parse_passport(passport.join(" "))
passport = [] of String
end
passports << parse_passport(passport.join(" "))
end end
def part1 def part1
@ -36,42 +26,33 @@ 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|
next unless value = passport["byr"]? validators.all? do |k, v|
value = value.to_i32 passport[k]?.try { |s| v.call(s) }
next unless value >= 1920 && value <= 2002
next unless value = passport["iyr"]?
value = value.to_i32
next unless value >= 2010 && value <= 2020
next unless value = passport["eyr"]?
value = value.to_i32
next unless value >= 2020 && value <= 2030
next unless value = passport["hgt"]?
next unless value.ends_with?("cm") || value.ends_with?("in")
ivalue = value[0..-3].to_i32
if value.ends_with? "cm"
next unless ivalue >= 150 && ivalue <= 193
else
next unless ivalue >= 59 && ivalue <= 76
end end
next unless value = passport["hcl"]?
next unless value[0] == '#' && (value[1..]).to_i32(16)
next unless value = passport["ecl"]?
next unless "amb blu brn gry grn hzl oth".split(" ").includes? value
next unless value = passport["pid"]?
next unless value.size == 9
next unless value = value.to_i32?
true
end end
puts total puts total
end end