Solve day 4, part 2

pull/1/head
Gaël Depreeuw 4 years ago
parent 38a9eb3c9f
commit 1cb7efa11a
Signed by: Mithror
GPG Key ID: 8AB218ABA4867F78
  1. 103
      src/Day4.hs

@ -9,19 +9,23 @@ import qualified Data.Map as M
import Data.Maybe (catMaybes)
import qualified Data.Text as T
type BYR = T.Text
data Height = CM Integer | IN Integer deriving (Show, Eq)
type IYR = T.Text
data EyeColour = AMB | BLU | BRN | GRY | GRN | HZL | OTH deriving (Show, Eq)
type EYR = T.Text
type BYR = Either String Integer
type HGT = T.Text
type IYR = Either String Integer
type HCL = T.Text
type EYR = Either String Integer
type ECL = T.Text
type HGT = Either String Height
type PID = T.Text
type HCL = Either String String
type ECL = Either String EyeColour
type PID = Either String Integer
type CID = T.Text
@ -47,16 +51,82 @@ parserPair = do
parserEntry :: P.Parser (M.Map T.Text T.Text)
parserEntry = M.fromList <$> parserPair `P.sepBy` (void P.space <|> P.endOfLine)
parseBYR :: T.Text -> BYR
parseBYR s = do
n <- P.eitherResult $ P.parse (P.count 4 P.digit) s
let n' = read n
if n' >= 1920 && n' <= 2002 then Right n' else Left (T.unpack s)
parseIYR :: T.Text -> IYR
parseIYR s = do
n <- P.eitherResult $ P.parse (P.count 4 P.digit) s
let n' = read n
if n' >= 2010 && n' <= 2020 then Right n' else Left (T.unpack s)
parseEYR :: T.Text -> EYR
parseEYR s = do
n <- P.eitherResult $ P.parse (P.count 4 P.digit) s
let n' = read n
if n' >= 2020 && n' <= 2030 then Right n' else Left (T.unpack s)
parseCM :: P.Parser Height
parseCM = do
n <- P.count 3 P.digit
_ <- P.string "cm"
let n' = read n
if n' >= 150 && n' <= 193
then return $ CM n'
else fail n
parseIN :: P.Parser Height
parseIN = do
n <- P.count 2 P.digit
_ <- P.string "in"
let n' = read n
if n' >= 59 && n' <= 76
then return $ IN n'
else fail n
parseHGT :: T.Text -> HGT
parseHGT s = P.eitherResult $ P.parse (parseCM <|> parseIN) s
parseHCL :: T.Text -> HCL
parseHCL s =
let p = P.char '#' *> P.count 6 (P.satisfy (P.inClass "a-f0-9"))
in P.eitherResult $ P.parse p s
parseECL :: T.Text -> ECL
parseECL s = do
let pAMB = AMB <$ P.string "amb"
pBLU = BLU <$ P.string "blu"
pBRN = BRN <$ P.string "brn"
pGRY = GRY <$ P.string "gry"
pGRN = GRN <$ P.string "grn"
pHZL = HZL <$ P.string "hzl"
pOTH = OTH <$ P.string "oth"
p = pAMB <|> pBLU <|> pBRN <|> pGRY <|> pGRN <|> pHZL <|> pOTH
in P.eitherResult $ P.parse p s
parsePID :: T.Text -> PID
parsePID s = fmap read (P.parseOnly (P.count 9 P.digit <* P.endOfInput) s)
fromMap :: M.Map T.Text T.Text -> Maybe Passport
fromMap m = do
byr <- m M.!? "byr"
let byr' = parseBYR byr
iyr <- m M.!? "iyr"
let iyr' = parseIYR iyr
eyr <- m M.!? "eyr"
let eyr' = parseEYR eyr
hgt <- m M.!? "hgt"
let hgt' = parseHGT hgt
hcl <- m M.!? "hcl"
let hcl' = parseHCL hcl
ecl <- m M.!? "ecl"
let ecl' = parseECL ecl
pid <- m M.!? "pid"
return $ Passport byr iyr eyr hgt hcl ecl pid (m M.!? "cid")
let pid' = parsePID pid
return $ Passport byr' iyr' eyr' hgt' hcl' ecl' pid' (m M.!? "cid")
parserPassport :: P.Parser (Maybe Passport)
parserPassport = fromMap <$> parserEntry
@ -68,8 +138,21 @@ parseList s =
Left s -> error (show s)
Right r -> r
validatePassport :: Passport -> Bool
validatePassport (Passport (Left _) _ _ _ _ _ _ _) = False
validatePassport (Passport _ (Left _) _ _ _ _ _ _) = False
validatePassport (Passport _ _ (Left _) _ _ _ _ _) = False
validatePassport (Passport _ _ _ (Left _) _ _ _ _) = False
validatePassport (Passport _ _ _ _ (Left _) _ _ _) = False
validatePassport (Passport _ _ _ _ _ (Left _) _ _) = False
validatePassport (Passport _ _ _ _ _ _ (Left _) _) = False
validatePassport _ = True
day4 :: IO ()
day4 = do
r <- readFile "./input/day4"
putStr "[Day 4-1] # trees: "
print . length . catMaybes . parseList $ r
putStr "[Day 4-1] # correct: "
let m = catMaybes . parseList $ r
print . length $ m
putStr "[Day 4-2] # more correct: "
print . length . filter validatePassport $ m
Loading…
Cancel
Save