0 | module Days.Day1
 1 |
 2 | import Data.String
 3 | import Data.List1
 4 | import System
 5 |
 6 | parseLine : String -> Maybe (Integer, Integer)
 7 | parseLine str =
 8 |   let parts = filter (not . null) . map trim . forget . split (== ' ') $ str
 9 |   in case parts of
10 |     [first, second] => do
11 |       first <- parseInteger first
12 |       second <- parseInteger second
13 |       Just (first, second)
14 |     x => Nothing
15 |
16 | parseInput : String -> Maybe (List Integer, List Integer)
17 | parseInput =
18 |   map unzip . traverse parseLine . lines
19 |
20 | totalDistance : List Integer -> List Integer -> Integer
21 | totalDistance xs ys =
22 |   sum . map distance $ zip (sort xs) (sort ys)
23 |   where
24 |     distance : (Integer, Integer) -> Integer
25 |     distance (x, y) =
26 |       if x > y
27 |       then x - y
28 |       else y - x
29 |
30 | export
31 | part1 : String -> IO (String, (List Integer, List Integer))
32 | part1 str =
33 |   case parseInput str of
34 |     Nothing => do
35 |       putStrLn "Failed to parse input string."
36 |       exitFailure
37 |     Just (xs, ys) => pure (show $ totalDistance xs ys, (xs, ys))
38 |
39 | similarityScore : List Integer -> List Integer -> Integer
40 | similarityScore xs ys =
41 |   sum . map (\x => x * natToInteger (count (== x) ys)) $ xs
42 |
43 | export
44 | part2 : (List Integer, List Integer) -> String -> IO String
45 | part2 (xs, ys) _ =
46 |   pure . show $ similarityScore xs ys
47 |