41 lines
1.3 KiB
Haskell
41 lines
1.3 KiB
Haskell
|
import Data.Char
|
||
|
import Data.List
|
||
|
import Data.List.Split
|
||
|
|
||
|
main :: IO ()
|
||
|
main = do
|
||
|
input <- map (unwords . lines) . splitOn "\n\n" <$> readFile "input"
|
||
|
print $ day4 input validateA
|
||
|
print $ day4 input validateB
|
||
|
|
||
|
day4 :: [String] -> ([[String]] -> Bool) -> Int
|
||
|
day4 input vldt = length $ filter vldt $ map (map (splitOn ":") . words) input
|
||
|
|
||
|
validateA :: [[String]] -> Bool
|
||
|
validateA =
|
||
|
null . (\\) ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"] . map head
|
||
|
|
||
|
validateB :: [[String]] -> Bool
|
||
|
validateB input = validateA input && all val input
|
||
|
where
|
||
|
val (x:xs)
|
||
|
| "byr" <- x = pars >= 1920 && pars <= 2002
|
||
|
| "iyr" <- x = pars >= 2010 && pars <= 2020
|
||
|
| "eyr" <- x = pars >= 2020 && pars <= 2030
|
||
|
| "hgt" <- x =
|
||
|
case partition isDigit b of
|
||
|
(y, "cm") -> read y >= 150 && read y <= 193
|
||
|
(y, "in") -> read y >= 59 && read y <= 76
|
||
|
_ -> False
|
||
|
| "hcl" <- x =
|
||
|
(head b == '#') &&
|
||
|
all (`elem` (['0' .. '9'] `union` ['a' .. 'f'])) (tail b) &&
|
||
|
(length b == 7)
|
||
|
| "ecl" <- x = b `elem` ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]
|
||
|
| "pid" <- x = length b == 9 && null (dropWhile isDigit b)
|
||
|
| "cid" <- x = True
|
||
|
| _ <- x = False
|
||
|
where
|
||
|
pars = read b
|
||
|
b = head xs
|