-
Notifications
You must be signed in to change notification settings - Fork 0
/
day13.hs
31 lines (23 loc) · 1.1 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
module Main where
import Data.Char (isDigit)
import Data.List (findIndices, sort)
import Data.List.Split (splitOn)
data Signal a = Packet a | Signal [Signal a] deriving (Show, Read, Eq)
instance (Eq a, Ord a) => Ord (Signal a) where
compare (Packet a) (Packet b) = a `compare` b
compare (Signal l1) (Signal l2) = l1 `compare` l2
compare a@(Packet _) (Signal l2) = [a] `compare` l2
compare (Signal l1) b@(Packet _) = l1 `compare` [b]
main = interact (unlines . sequence [part1, part2] . map (map signal . lines) . splitOn "\n\n")
part1, part2 :: [[Signal Int]] -> String
part1 = ("Part 1: " ++) . show . sum . map fst . filter ((\[a, b] -> a <= b) . snd) . zip [1 ..]
part2 = ("Part 2: " ++) . show . product . map (+ 1) . findIndices (`elem` dividers) . sort . foldr (++) dividers
dividers = [signal "[[2]]", signal "[[6]]"]
signal :: Read a => String -> Signal a
signal = read . signal'
signal' :: String -> String
signal' [] = ""
signal' ('[' : xs) = "Signal [" ++ signal' xs
signal' (c : xs)
| isDigit c = let (s, e) = span isDigit xs in "Packet " ++ c : s ++ signal' e
| otherwise = c : signal' xs