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