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
|
||||
```
|
||||
|
||||
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