-
Notifications
You must be signed in to change notification settings - Fork 0
/
day4.hs
58 lines (45 loc) · 1.99 KB
/
day4.hs
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
import Data.List
import Data.Maybe
type Interval = (Int, Int)
-- determine whether two lists fully overlap
fullyOverlap :: Eq a => [a] -> [a] -> Bool
fullyOverlap xs ys = xs `intersect` ys == xs || xs `intersect` ys == ys
-- determine whether two lists partly overlap
partlyOverlap :: Eq a => [a] -> [a] -> Bool
partlyOverlap xs ys = xs `intersect` ys /= []
-- parse a line
parseLine :: String -> (String, String)
parseLine = splitOn ','
-- parse a pair
parsePair :: String -> Interval
parsePair = toInts . splitOn '-'
where toInts = \(x, y) -> (read x, read y)
-- split a string on a character into a pair
splitOn :: Char -> String -> (String, String)
splitOn c xs = (take i xs, drop (i + 1) xs)
where i = fromJust $ elemIndex c xs
-- parse the input
parse :: String -> [(Interval, Interval)]
parse xs = map (\(x, y) -> (parsePair x, parsePair y)) $ map (parseLine) $ filter (\l -> l /= "") $ lines xs
-- convert an interval to a list
intervalToList :: Interval -> [Int]
intervalToList (s, e) = [s..e]
-- check if two elves have overlapping ranges
intervalsFullyOverlap :: (Interval, Interval) -> Bool
intervalsFullyOverlap (x, y) = fullyOverlap (intervalToList x) (intervalToList y)
-- check if two elves have overlapping ranges
intervalsPartlyOverlap :: (Interval, Interval) -> Bool
intervalsPartlyOverlap (x, y) = partlyOverlap (intervalToList x) (intervalToList y)
-- count the number of range overlaps given some input and predicate
overlapsBy :: ((Interval, Interval) -> Bool) -> String -> Int
overlapsBy f = length . filter (== True) . map f . parse
-- count the number of full overlaps in assignments
part1 :: String -> IO Int
part1 fileName = do contents <- readFile fileName
let os = overlapsBy intervalsFullyOverlap contents
return os
-- count the number of partial overlaps in assignments
part2 :: String -> IO Int
part2 fileName = do contents <- readFile fileName
let os = overlapsBy intervalsPartlyOverlap contents
return os