diff --git a/13-a.hs b/13-a.hs new file mode 100644 index 0000000..fe01386 --- /dev/null +++ b/13-a.hs @@ -0,0 +1,52 @@ +import Prelude +import Data.List.Split (splitOn) +import Data.Char (isNumber) +import Data.List (elemIndices) + +{- cabal: +build-depends: base, split +-} + +data Node = List [Node] | Num Int + deriving (Eq, Show) + +compareNodes :: Node -> Node -> Ordering +-- two ints +compareNodes (Num x) (Num y) = compare x y +-- two lists +compareNodes (List []) (List []) = EQ +compareNodes (List _) (List []) = GT +compareNodes (List []) (List _) = LT +compareNodes (List (x:xs)) (List (y:ys)) + | r /= EQ = r + | otherwise = compareNodes (List xs) (List ys) + where r = compareNodes x y +-- mixed +compareNodes (Num x) (List y) = compareNodes (List [Num x]) (List y) +compareNodes (List x) (Num y) = compareNodes (List x) (List [Num y]) + +-- "1,[2,3],4,[5,[6,7]]" -> ["1","[2,3]","4","[5,[6,7]]"] +parseList :: String -> [String] +parseList = go 0 "" + where + go :: Int -> String -> String -> [String] + go 0 "" [] = [] + go 0 accum [] = [accum] + go _ _ [] = error "unclosed parens" + go depth accum (c:xs) + | c == '[' = go (depth + 1) (accum ++ [c]) xs + | c == ']' = go (depth - 1) (accum ++ [c]) xs + | c == ',' && depth == 0 = accum : go depth "" xs + | otherwise = go depth (accum ++ [c]) xs + +parseNode :: String -> Node +parseNode s + | head s == '[' && last s == ']' = List $ map parseNode $ parseList (reverse $ drop 1 $ reverse $ drop 1 s) + | all isNumber s = Num $ read s + | otherwise = error s + +main = interact $ + show + . sum . map (+ 1) . elemIndices LT + . map ((\[a, b] -> a `compareNodes` b) . map parseNode . lines) + . splitOn "\n\n" \ No newline at end of file diff --git a/13-b.hs b/13-b.hs new file mode 100644 index 0000000..097abeb --- /dev/null +++ b/13-b.hs @@ -0,0 +1,57 @@ +import Prelude +import Data.List.Split (splitOn) +import Data.Char (isNumber) +import Data.List (sortBy, findIndices, intercalate) + +{- cabal: +build-depends: base, split +-} + +data Node = List [Node] | Num Int + deriving (Eq, Show) + +compareNodes :: Node -> Node -> Ordering +-- two ints +compareNodes (Num x) (Num y) = compare x y +-- two lists +compareNodes (List []) (List []) = EQ +compareNodes (List _) (List []) = GT +compareNodes (List []) (List _) = LT +compareNodes (List (x:xs)) (List (y:ys)) + | r /= EQ = r + | otherwise = compareNodes (List xs) (List ys) + where r = compareNodes x y +-- mixed +compareNodes (Num x) (List y) = compareNodes (List [Num x]) (List y) +compareNodes (List x) (Num y) = compareNodes (List x) (List [Num y]) + +-- "1,[2,3],4,[5,[6,7]]" -> ["1","[2,3]","4","[5,[6,7]]"] +parseList :: String -> [String] +parseList = go 0 "" + where + go :: Int -> String -> String -> [String] + go 0 "" [] = [] + go 0 accum [] = [accum] + go _ _ [] = error "unclosed parens" + go depth accum (c:xs) + | c == '[' = go (depth + 1) (accum ++ [c]) xs + | c == ']' = go (depth - 1) (accum ++ [c]) xs + | c == ',' && depth == 0 = accum : go depth "" xs + | otherwise = go depth (accum ++ [c]) xs + +parseNode :: String -> Node +parseNode s + | head s == '[' && last s == ']' = List $ map parseNode $ parseList (reverse $ drop 1 $ reverse $ drop 1 s) + | all isNumber s = Num $ read s + | otherwise = error s + +dividerPackets = [List [List [Num 2]], List [List [Num 6]]] + +main = interact $ + show + . product + . map (+ 1) . findIndices (`elem` dividerPackets) + . sortBy compareNodes + . (++ dividerPackets) + . map parseNode + . filter (not . null) . lines \ No newline at end of file diff --git a/13-extra.hs b/13-extra.hs new file mode 100644 index 0000000..47abe8f --- /dev/null +++ b/13-extra.hs @@ -0,0 +1,10 @@ +import Data.List (intercalate) + +data Node = List [Node] | Num Int + deriving (Eq) + +-- here's a Show instance for Node that recreates the input: + +instance Show Node where + show (List x) = "[" ++ intercalate "," (map show x) ++ "]" + show (Num n) = show n \ No newline at end of file diff --git a/README.md b/README.md index d1af586..d9bd336 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,6 @@ you shouldn't; but for documentation purposes it's $ ghc 1-a.hs && cat 1_input | ./1-a ``` -you'll need to retrieve `1_input` from your aoc, but all programs will strictly take in the aoc input and ~~output what can be pasted into the anwser field~~ (thanks, day 10 part 2!) \ No newline at end of file +you'll need to retrieve `1_input` from your aoc, but all programs will strictly take in the aoc input and ~~output what can be pasted into the anwser field~~ (thanks, day 10 part 2!) + +occasionally, i'll also leave `-extra.hs` files for misc stuff i never ended up using but was neat anyways and i wanted to preserve \ No newline at end of file