day 13
This commit is contained in:
parent
299beb9c73
commit
c316ce45dd
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -10,4 +10,6 @@ you shouldn't; but for documentation purposes it's
|
||||||
$ ghc 1-a.hs && cat 1_input | ./1-a
|
$ 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!)
|
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
|
Loading…
Reference in New Issue