48744d4fe65190bb4d81633d4330f0e2f85072f4
[aoc20.git] / 4 / one.icl
1 module one
2
3 import StdEnv
4 import Text
5 import Data.Functor
6 import Data.Maybe
7 import Data.List
8 import Regex
9
10 read :: *File -> [String]
11 read f
12 # (l, f) = freadline f
13 | l.[size l - 1] == '\0' = []
14 = [l % (0, size l - 2):read f]
15
16 group :: [(String, String)] [String] -> [[(String, String)]]
17 group acc [] = [acc]
18 group acc ["":xs] = [acc:group [] xs]
19 group acc [s:xs] = group (acc ++ [(k, v)\\[k,v]<-map (split ":") (split " " s)]) xs
20
21 valid :: [(String, String -> Bool)] [(String, String)] -> Bool
22 valid req fs = all (\(f, p)->fromMaybe False (p <$> lookup f fs)) req
23
24 Start w
25 # (io, w) = stdio w
26 # passports = group [] (read io)
27 = (one passports, two passports)
28
29 one = length o filter (valid [(n, const True)\\n<-["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]])
30
31 two = length o filter (valid
32 [ ("byr", fourDigit 1920 2002)
33 , ("iyr", fourDigit 2010 2020)
34 , ("eyr", fourDigit 2020 2030)
35 , ("hgt", \x->case x % (size x - 2, size x - 1) of
36 "cm" = between 150 193 (toInt (x % (0, size x - 3)))
37 "in" = between 59 76 (toInt (x % (0, size x - 3)))
38 _ = False)
39 , ("hcl", reg "#[0-9a-f]{6}")
40 , ("ecl", flip isMember ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"])
41 , ("pid", reg "\\d{9}")
42 ])
43 fourDigit lo hi x = reg "\\d{4}" x && between lo hi (toInt x)
44 reg p = not o isEmpty o match p
45 between lo hi x = x >= lo && x <= hi