module one import StdEnv import Text import Data.Functor import Data.Maybe import Data.List import Regex read :: *File -> [String] read f # (l, f) = freadline f | l.[size l - 1] == '\0' = [] = [l % (0, size l - 2):read f] group :: [(String, String)] [String] -> [[(String, String)]] group acc [] = [acc] group acc ["":xs] = [acc:group [] xs] group acc [s:xs] = group (acc ++ [(k, v)\\[k,v]<-map (split ":") (split " " s)]) xs valid :: [(String, String -> Bool)] [(String, String)] -> Bool valid req fs = all (\(f, p)->fromMaybe False (p <$> lookup f fs)) req Start w # (io, w) = stdio w # passports = group [] (read io) = (one passports, two passports) one = length o filter (valid [(n, const True)\\n<-["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]]) two = length o filter (valid [ ("byr", fourDigit 1920 2002) , ("iyr", fourDigit 2010 2020) , ("eyr", fourDigit 2020 2030) , ("hgt", \x->case x % (size x - 2, size x - 1) of "cm" = between 150 193 (toInt (x % (0, size x - 3))) "in" = between 59 76 (toInt (x % (0, size x - 3))) _ = False) , ("hcl", reg "#[0-9a-f]{6}") , ("ecl", flip isMember ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]) , ("pid", reg "\\d{9}") ]) fourDigit lo hi x = reg "\\d{4}" x && between lo hi (toInt x) reg p = not o isEmpty o match p between lo hi x = x >= lo && x <= hi