-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay13.hs
61 lines (52 loc) · 1.86 KB
/
Day13.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
59
60
61
module Day13 (solve) where
import Data.Function ( (&) )
import Data.List
data Msg = Num Int | List [Msg] deriving (Show, Eq)
instance Ord Msg where
compare (Num a) (Num b) = compare a b
compare (List a) (List b) = compare a b
compare number@(Num _) list@(List _) = compare (List [number]) list
compare list@(List _) number@(Num _) = compare list (List [number])
solve input lines = do
let pairs = paras lines
print $
pairs
& map (\ [l1, l2] -> readMsg l1 < readMsg l2)
& zip [1..]
& filter snd
& map fst
& sum
let (div2, div6) = (readMsg "[[2]]", readMsg "[[6]]")
let sorted =
lines
& filter (/= "")
& map readMsg
& (\ lns -> div2:div6:lns)
& sort
let (Just idx1, Just idx2) = (elemIndex div2 sorted, elemIndex div6 sorted)
print $ (idx1 + 1) * (idx2 + 1)
readMsg line = do
readMsg line & fst
where
readList :: [Msg] -> String -> (Msg, String)
readList parts (']':rest) =
(List (reverse parts), rest)
readList parts (',':rest) =
readList parts rest
readList parts txt = do
let (msg, rest') = readMsg txt
readList (msg:parts) rest'
readNumber :: [Char] -> String -> (Msg, String)
readNumber digits (d:rest@(nxt:_))
| nxt == ',' || nxt == ']' = (Num (read (reverse (d:digits))), rest)
| otherwise = readNumber (d:digits) rest
readMsg :: String -> (Msg, String)
readMsg ('[':rest) = readList [] rest
readMsg txt = readNumber [] txt
paras =
paras [[]]
where
paras :: [[String]] -> [String] -> [[String]]
paras grps [] = grps & map reverse & reverse
paras grps ("":lns) = paras ([]:grps) lns
paras (grp:grps) (ln:lns) = paras ((ln:grp):grps) lns