@@ -8,7 +8,10 @@ build-type:    Simple
 | 
			
		||||
 | 
			
		||||
common common
 | 
			
		||||
  ghc-options:        -Wall -O3
 | 
			
		||||
  default-extensions: LambdaCase
 | 
			
		||||
  default-extensions:
 | 
			
		||||
    LambdaCase
 | 
			
		||||
    ViewPatterns
 | 
			
		||||
 | 
			
		||||
  build-depends:
 | 
			
		||||
    , base    >=4.14 && <5
 | 
			
		||||
    , parsec  >=3
 | 
			
		||||
@@ -17,7 +20,6 @@ library libaoc
 | 
			
		||||
  import:          common
 | 
			
		||||
  exposed:         False
 | 
			
		||||
  hs-source-dirs:  lib
 | 
			
		||||
  build-depends:   containers
 | 
			
		||||
  exposed-modules: AoC
 | 
			
		||||
 | 
			
		||||
executable day1
 | 
			
		||||
@@ -49,3 +51,11 @@ executable day4alt
 | 
			
		||||
  hs-source-dirs: src
 | 
			
		||||
  main-is:        Day4Alt.hs
 | 
			
		||||
  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