diff --git a/day13.hs b/day13.hs new file mode 100644 index 0000000..ead102c --- /dev/null +++ b/day13.hs @@ -0,0 +1,59 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ViewPatterns #-} + +import Data.Char (isDigit) +import Data.List (elemIndex, sort) +import Data.Maybe (fromJust) +import Data.Text (Text) +import qualified Data.Text as T (filter, init, lines, null, span, tail, uncons) +import qualified Data.Text.Read as T (decimal) +import Lib (readFile') + +main :: IO () +main = do + input <- + map (fst . parse (List []) . T.init . T.tail) . filter (not . T.null) + . T.lines + <$> readFile' "day13.in" + putStr "Q1: " + print $ q1 input + putStr "Q2: " + print $ q2 input (List [List [Elem 2]]) (List [List [Elem 6]]) + +q1 :: [List] -> Int +q1 input = + foldl + (\xs x -> xs + if input !! (2 * x - 2) < input !! (2 * x - 1) then x else 0) + 0 + [1 .. length input `div` 2] + +q2 :: [List] -> List -> List -> Int +q2 input a b = + let sorted = sort (a : b : input) + a' = fromJust $ elemIndex a sorted + b' = fromJust $ elemIndex b sorted + in (a' + 1) * (b' + 1) + +data List = Elem Int | List [List] deriving (Show, Eq) + +-- is this cheating :P +instance Ord List where + compare (List xs) (List ys) = compare (reverse xs) (reverse ys) + compare (List xs) (Elem y) = compare (List xs) (List [Elem y]) + compare (Elem x) (List ys) = compare (List [Elem x]) (List ys) + compare (Elem x) (Elem y) = compare x y + +-- Weak parser but it works +-- I do not really know how to use Parsec and ReadP with Data.Text yet + +parse :: List -> Text -> (List, Text) +parse (List xs) txt + | T.null txt || cur == ']' = (List xs, rest) + | cur == '[' = + let (new, next) = parse (List []) rest + in parse (List (new : xs)) next + | isDigit cur = parse (List (Elem num : xs)) rest' + | otherwise = parse (List xs) rest + where + (cur, rest) = fromJust $ T.uncons txt + (T.decimal -> Right (num, ""), rest') = T.span isDigit txt