-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay4.hs
More file actions
97 lines (80 loc) · 2.33 KB
/
Copy pathDay4.hs
File metadata and controls
97 lines (80 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
module Day4
( part1
, part2
) where
import Data.List.Split (splitWhen)
import Data.Map (fromList, (!))
import Data.Maybe (Maybe (Just), isJust)
import Data.Void
import Helpers.Parsers (alnum, custom)
import Text.Megaparsec (Parsec, oneOf, some, (<|>))
import Text.Read (readMaybe)
parser =
fromList
[ ("byr", byr)
, ("iyr", iyr)
, ("eyr", eyr)
, ("hgt", hgt)
, ("hcl", hcl)
, ("ecl", ecl)
, ("pid", pid)
, ("cid", cid)
]
customised :: Parsec Void String (Maybe String)
customised =
fmap Just . some . oneOf $ '#' : ['a' .. 'z'] ++ ['A' .. 'Z'] ++ ['0' .. '9']
isValid :: [(String, String)] -> Bool
isValid = all validPair
validPair :: (String, String) -> Bool
validPair (i, v) = (parser ! i) v
byr :: String -> Bool
byr s = isJust rms && rs >= 1920 && rs <= 2002
where
rms = readMaybe s
(Just rs) = rms
iyr :: String -> Bool
iyr s = isJust rms && rs >= 2010 && rs <= 2020
where
rms = readMaybe s
(Just rs) = rms
eyr :: String -> Bool
eyr s = isJust rms && rs >= 2020 && rs <= 2030
where
rms = readMaybe s
(Just rs) = rms
hgt :: String -> Bool
hgt s
| length s == 5 = isJust rms3 && rs3 >= 150 && rs3 <= 193 && drop 3 s == "cm"
| length s == 4 = isJust rms2 && rs2 >= 59 && rs2 <= 76 && drop 2 s == "in"
| otherwise = False
where
rms3 = readMaybe . take 3 $ s
(Just rs3) = rms3
rms2 = readMaybe . take 2 $ s
(Just rs2) = rms2
hcl :: String -> Bool
hcl (x:xs) =
length xs == 6 && x == '#' && all (`elem` (['0' .. '9'] ++ ['a' .. 'f'])) xs
ecl :: String -> Bool
ecl s = s `elem` ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]
pid :: String -> Bool
pid s = length s == 9 && isJust (readMaybe s :: Maybe Int)
cid :: String -> Bool
cid _ = True
hasAllFields :: [String] -> Bool
hasAllFields s =
not . any (`notElem` s) $ ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]
toPairs :: [String] -> [(String, String)]
toPairs [] = []
toPairs (a:b:xs) = (a, b) : toPairs xs
part1 :: Bool -> String -> String
part1 _ =
show .
length . filter hasAllFields . map concat . splitWhen null . custom customised
part2 :: Bool -> String -> String
part2 _ =
show .
length .
filter isValid .
map toPairs .
filter hasAllFields . map concat . splitWhen null . custom customised