We're a place where coders share, stay up-to-date and grow their careers.
Here is a Haskell soloution for Day 4:
-- check if a given "passport" field is a valid passport field isValidField :: (T.Text, T.Text) -> Bool isValidField (name,v) | name == "byr" = fourAux 1920 2002 | name == "iyr" = fourAux 2010 2020 | name == "eyr" = fourAux 2020 2030 | name == "ecl" = v `elem` ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"] | name == "hcl" = let h = T.head v == '#' ts = T.tail v in h && T.length ts == 6 && elementOf "0123456789abcdef" ts | name == "pid" = either (const False) (\_ -> T.length v == 9) (decimal v) | name == "hgt" = let (n,t) = (fst $ fromRight (0,"") (decimal (T.takeWhile (not . isAlpha) v)), T.dropWhile (not . isAlpha) v) in (t == "cm" && n >= 150 && n <= 193) || (t == "in" && n >= 59 && n <= 76) | otherwise = name == "cid" where fourAux min max = let n = fst $ fromRight (0,"") (decimal v) in n >= min && n <= max && T.length v == 4 elementOf :: String -> T.Text -> Bool elementOf xs = T.all (`elem` xs) -- check if a input field is a actually within the set of valid passport fields isValidFieldName xs = all (`elem` xs) ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"] isValidPassport :: [(T.Text, T.Text)] -> Bool isValidPassport xs = all isValidField xs && (isValidFieldName $ map fst xs) -- generate a list of passports, given a list of input lines passports :: [T.Text] -> [[(T.Text, T.Text)]] passports = docs [] [] where docs doc ds [] = doc:ds docs doc ds ("":xs) = docs [] (doc:ds) xs docs doc ds (x:xs) = docs (mkKey x ++ doc) ds xs mkKey = map (\xs -> (T.takeWhile (/=':') xs, T.tail (T.dropWhile (/=':') xs))) . splitOn " " main = do xs <- IOT.readFile "day4_input" <&> T.lines print (length $ filter isValidFieldName (map (map fst) $ passports xs)) print (length (filter isValidPassport (passports xs)))
Here is a Haskell soloution for Day 4: