@@ -8,7 +8,10 @@ build-type: Simple
|
|||||||
|
|
||||||
common common
|
common common
|
||||||
ghc-options: -Wall -O3
|
ghc-options: -Wall -O3
|
||||||
default-extensions: LambdaCase
|
default-extensions:
|
||||||
|
LambdaCase
|
||||||
|
ViewPatterns
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
, base >=4.14 && <5
|
, base >=4.14 && <5
|
||||||
, parsec >=3
|
, parsec >=3
|
||||||
@@ -17,7 +20,6 @@ library libaoc
|
|||||||
import: common
|
import: common
|
||||||
exposed: False
|
exposed: False
|
||||||
hs-source-dirs: lib
|
hs-source-dirs: lib
|
||||||
build-depends: containers
|
|
||||||
exposed-modules: AoC
|
exposed-modules: AoC
|
||||||
|
|
||||||
executable day1
|
executable day1
|
||||||
@@ -49,3 +51,11 @@ executable day4alt
|
|||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
main-is: Day4Alt.hs
|
main-is: Day4Alt.hs
|
||||||
build-depends: libaoc
|
build-depends: libaoc
|
||||||
|
|
||||||
|
executable day5
|
||||||
|
import: common
|
||||||
|
hs-source-dirs: src
|
||||||
|
main-is: Day5.hs
|
||||||
|
build-depends:
|
||||||
|
, containers
|
||||||
|
, libaoc
|
||||||
|
50
src/Day5.hs
Normal file
50
src/Day5.hs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import qualified AoC as A (extract)
|
||||||
|
import Data.Bool (bool)
|
||||||
|
import Data.List (sortBy, tails)
|
||||||
|
import qualified Data.Set as S
|
||||||
|
import Text.Parsec (char, digit, many1, newline, parse, sepBy1, sepEndBy1)
|
||||||
|
import Text.Parsec.String (Parser)
|
||||||
|
|
||||||
|
type Rule = (Int, Int)
|
||||||
|
|
||||||
|
type Rules = S.Set Rule
|
||||||
|
|
||||||
|
type Update = [Int]
|
||||||
|
|
||||||
|
parseRules :: Parser (Rules, [Update])
|
||||||
|
parseRules = do
|
||||||
|
rules <- S.fromList <$> parseRule `sepEndBy1` newline
|
||||||
|
newline
|
||||||
|
updates <- parseUpdate `sepEndBy1` newline
|
||||||
|
return (rules, updates)
|
||||||
|
where
|
||||||
|
parseRule :: Parser Rule
|
||||||
|
parseRule = (,) <$> (read <$> many1 digit <* char '|') <*> (read <$> many1 digit)
|
||||||
|
parseUpdate :: Parser Update
|
||||||
|
parseUpdate = (read <$> many1 digit) `sepBy1` char ','
|
||||||
|
|
||||||
|
middle :: [a] -> a
|
||||||
|
middle xs = xs !! (length xs `div` 2)
|
||||||
|
|
||||||
|
isOrdered :: Rules -> Update -> Bool
|
||||||
|
isOrdered rules (first : rest) = all (flip S.member rules . (,) first) rest
|
||||||
|
isOrdered _ _ = False
|
||||||
|
|
||||||
|
part1 :: Rules -> [Update] -> Int
|
||||||
|
part1 rules = sum . map middle . filter (all (isOrdered rules) . init . tails)
|
||||||
|
|
||||||
|
part2 :: Rules -> [Update] -> Int
|
||||||
|
part2 rules =
|
||||||
|
sum
|
||||||
|
. map (middle . sortBy (\x -> bool GT LT . flip S.member rules . (,) x))
|
||||||
|
. filter (not . all (isOrdered rules) . init . tails)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main =
|
||||||
|
do
|
||||||
|
raw <- readFile "./inputs/day5.in"
|
||||||
|
let (rules, updates) = A.extract $ parse parseRules "" raw
|
||||||
|
putStr "Part 1: " >> print (part1 rules updates)
|
||||||
|
putStr "Part 2: " >> print (part2 rules updates)
|
Reference in New Issue
Block a user