Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {-# LANGUAGE OverloadedStrings #-}
- import Data.Text.IO (readFile)
- import qualified Data.Text.IO as TIO
- import Data.Text (Text)
- import qualified Data.Text as T
- import Data.Attoparsec.Text
- import Control.Applicative
- import Data.Map (Map, (!))
- import qualified Data.Map as M
- import Data.Char (isSpace, isDigit)
- type Passport = Map Text Text
- parseKVP :: Parser (Text, Text)
- parseKVP = do
- k <- T.pack <$> many1 letter
- char ':'
- v <- takeWhile1 (not . isSpace)
- return (k, v)
- parsePassport :: Parser Passport
- parsePassport = M.fromList <$> parseKVP `sepBy1` space
- validatePassport :: Passport -> Bool
- validatePassport p = all (`M.member` p) requiredFields
- where
- requiredFields = ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"] -- no "cid"
- validatePassport2 :: Passport -> Bool
- validatePassport2 = M.foldrWithKey (\k v b -> (fieldValidators!k) v && b) True
- where
- tRead = read . T.unpack
- fieldValidators = M.fromList
- [ ("byr", byr)
- , ("iyr", iyr)
- , ("eyr", eyr)
- , ("hgt", hgt)
- , ("hcl", hcl)
- , ("ecl", ecl)
- , ("pid", pid)
- , ("cid", const True)
- ]
- byr v = T.length v == 4 && T.all isDigit v && 1920 <= tRead v && tRead v <= 2002
- iyr v = T.length v == 4 && T.all isDigit v && 2010 <= tRead v && tRead v <= 2020
- eyr v = T.length v == 4 && T.all isDigit v && 2020 <= tRead v && tRead v <= 2030
- hgt v = case unit of
- "cm" -> 150 <= n && n <= 193
- "in" -> 59 <= n && n <= 76
- _ -> False
- where
- n = tRead $ T.dropEnd 2 v
- unit = T.takeEnd 2 v
- hcl v = T.head v == '#' && T.length color == 6 && T.all (\c -> ('0'<=c && c<='9') || ('a'<=c && c<='f')) color
- where color = T.drop 1 v
- ecl v = (v == "amb") || (v == "blu") || (v == "blu") || (v == "gry") || (v == "grn") || (v == "hzl") || (v == "oth")
- pid v = T.length v == 9 && T.all isDigit v
- main :: IO ()
- main = do
- input <- TIO.readFile "input.txt"
- let passports = case parseOnly (parsePassport `sepBy1` many1 space) input of
- Left err -> error $ "Parsing error: " ++ err
- Right out -> out
- putStrLn "Part 1:"
- print . length . filter validatePassport $ passports
- putStrLn "Part 2:"
- print . length . filter validatePassport2 $ passports -- this is right...
- print . length . filter ((&&) <$> validatePassport <*> validatePassport2) $ passports -- but this is wrong??
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement