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
|
module Day16A where
import System.Environment (getArgs)
import Text.Printf
import Data.List.Split (splitOn)
-- name, (lo, hi)
type FieldDef = (String, [(Int, Int)])
-- (fields, your ticket, nearby tickets)
type Input = ([FieldDef], [Int], [[Int]])
parseTicketLine :: String -> [Int]
parseTicketLine = map read . splitOn ","
parseRange :: String -> (Int, Int)
parseRange x = (head ns, last ns)
where ns = map read $ splitOn "-" x
parseFieldDef :: String -> FieldDef
parseFieldDef x = (n, ranges)
where [n, rs] = splitOn ": " x
ranges = map parseRange $ splitOn " or " rs
parseFields :: [String] -> [FieldDef]
parseFields = inner . head . splitOn [""]
where inner = map parseFieldDef
findYourTicket :: [String] -> [Int]
findYourTicket ("your ticket:":xs) = parseTicketLine (head xs)
findYourTicket (_:xs) = findYourTicket xs
findYourTicket [] = error "Couldn't find your ticket"
findOtherTickets :: [String] -> [[Int]]
findOtherTickets ("nearby tickets:":xs) = map parseTicketLine xs
findOtherTickets (_:xs) = findOtherTickets xs
findOtherTickets [] = error "Couldn't find nearby tickets"
-- Parse the input
parseInput :: String -> Input
parseInput xs = (parseFields ls, findYourTicket ls, findOtherTickets ls)
where ls = lines xs
-- Parse a file given the path
-- Returns list of instructions
parseFromFile :: String -> IO Input
parseFromFile s = do
contents <- readFile s;
return $ parseInput contents;
fieldValid :: FieldDef -> Int -> Bool
fieldValid (_, rs) x = any (\(l,h) -> x >= l && x <= h) rs
invalidValues :: Input -> [Int]
invalidValues (cs, _, ts) = concat [filter (\x -> not (any (`fieldValid` x) cs)) t | t <- ts]
-- runghc --ghc-arg='-package split' 16a.hs inputs/day16
main :: IO ()
main = do
args <- getArgs;
i <- parseFromFile (head args);
let vs = invalidValues i;
printf "Answer = %d\n" (sum vs) :: IO ();
return ();
|