Add solution to day 5.
This commit is contained in:
parent
9b6682c56f
commit
3f63454ce0
6 changed files with 1508 additions and 1 deletions
74
2024/haskell/app/day5/Day5.hs
Normal file
74
2024/haskell/app/day5/Day5.hs
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
module Main (main) where
|
||||||
|
|
||||||
|
import Data.List (elemIndex)
|
||||||
|
import Data.Maybe (fromJust)
|
||||||
|
import Lib.Parser (Parser (parse), char, many1, number, separated)
|
||||||
|
|
||||||
|
-- | Part 1
|
||||||
|
newtype Rule = Rule (Int, Int) deriving (Show)
|
||||||
|
|
||||||
|
newtype Update = Update [Int] deriving (Show)
|
||||||
|
|
||||||
|
rule :: Parser Rule
|
||||||
|
rule = (\a _ b -> Rule (a, b)) <$> number <*> char '|' <*> number
|
||||||
|
|
||||||
|
update :: Parser Update
|
||||||
|
update = Update <$> char ',' `separated` number
|
||||||
|
|
||||||
|
safetyManual :: Parser ([Rule], [Update])
|
||||||
|
safetyManual = filterParsed <$> many1 rule' <*> char '\n' <*> many1 update'
|
||||||
|
where
|
||||||
|
filterParsed :: [Rule] -> Char -> [Update] -> ([Rule], [Update])
|
||||||
|
filterParsed r _ u = (r, u)
|
||||||
|
|
||||||
|
rule' :: Parser Rule
|
||||||
|
rule' = const <$> rule <*> char '\n'
|
||||||
|
|
||||||
|
update' :: Parser Update
|
||||||
|
update' = const <$> update <*> char '\n'
|
||||||
|
|
||||||
|
validateRule :: Update -> Rule -> Bool
|
||||||
|
validateRule (Update u) (Rule (a, b)) = validateRule' $ (<) <$> elemIndex a u <*> elemIndex b u
|
||||||
|
where
|
||||||
|
validateRule' :: Maybe Bool -> Bool
|
||||||
|
validateRule' Nothing = True
|
||||||
|
validateRule' (Just result) = result
|
||||||
|
|
||||||
|
validateRules :: [Rule] -> Update -> Bool
|
||||||
|
validateRules rules upd = all (validateRule upd) rules
|
||||||
|
|
||||||
|
middle :: Update -> Int
|
||||||
|
middle (Update u) = u !! (length u `div` 2)
|
||||||
|
|
||||||
|
validUpdates :: ([Rule], [Update]) -> [Update]
|
||||||
|
validUpdates (r, u) = filter (validateRules r) u
|
||||||
|
|
||||||
|
part1 :: String -> IO ()
|
||||||
|
part1 s = print $ sum $ map middle $ validUpdates $ fst $ fromJust $ parse safetyManual s
|
||||||
|
|
||||||
|
-- | Part 2
|
||||||
|
invalidUpdates :: ([Rule], [Update]) -> [Update]
|
||||||
|
invalidUpdates (r, u) = filter (not . validateRules r) u
|
||||||
|
|
||||||
|
insertPage :: [Rule] -> Int -> Update -> Update
|
||||||
|
insertPage rules page (Update pages) = insertPage' rules pages page 0
|
||||||
|
where
|
||||||
|
insertPage' :: [Rule] -> [Int] -> Int -> Int -> Update
|
||||||
|
insertPage' [] pages' page' minViable = let (ps,ps') = splitAt minViable pages' in Update $ ps ++ [page'] ++ ps'
|
||||||
|
insertPage' _ [] page' _ = Update [page']
|
||||||
|
insertPage' ((Rule (a, b)):rs) pages' page' minViable
|
||||||
|
| page' == b && a `elem` pages' = insertPage' rs pages' page' (max minViable (((+1) . fromJust . elemIndex a) pages'))
|
||||||
|
| otherwise = insertPage' rs pages page minViable
|
||||||
|
|
||||||
|
fixUpdate :: [Rule] -> Update -> Update
|
||||||
|
fixUpdate rules (Update pages) = foldr (insertPage rules) (Update []) pages
|
||||||
|
|
||||||
|
part2 :: String -> IO ()
|
||||||
|
part2 s =
|
||||||
|
let (rules, updates) = (fst . fromJust . parse safetyManual) s
|
||||||
|
invUpd = invalidUpdates (rules, updates)
|
||||||
|
in print $ sum $ map (middle . fixUpdate rules) invUpd
|
||||||
|
|
||||||
|
-- | Main
|
||||||
|
main :: IO ()
|
||||||
|
main = readFile "resources/day5.txt" >>= part2
|
||||||
|
|
@ -94,6 +94,20 @@ executable day4
|
||||||
, haskell
|
, haskell
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable day5
|
||||||
|
main-is: Day5.hs
|
||||||
|
other-modules:
|
||||||
|
Paths_haskell
|
||||||
|
autogen-modules:
|
||||||
|
Paths_haskell
|
||||||
|
hs-source-dirs:
|
||||||
|
app/day5
|
||||||
|
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends:
|
||||||
|
base >=4.7 && <5
|
||||||
|
, haskell
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
test-suite haskell-test
|
test-suite haskell-test
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
main-is: Spec.hs
|
main-is: Spec.hs
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,16 @@ executables:
|
||||||
dependencies:
|
dependencies:
|
||||||
- haskell
|
- haskell
|
||||||
|
|
||||||
|
day5:
|
||||||
|
main: Day5.hs
|
||||||
|
source-dirs: app/day5
|
||||||
|
ghc-options:
|
||||||
|
- -threaded
|
||||||
|
- -rtsopts
|
||||||
|
- -with-rtsopts=-N
|
||||||
|
dependencies:
|
||||||
|
- haskell
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
haskell-test:
|
haskell-test:
|
||||||
main: Spec.hs
|
main: Spec.hs
|
||||||
|
|
|
||||||
1377
2024/haskell/resources/day5.txt
Normal file
1377
2024/haskell/resources/day5.txt
Normal file
File diff suppressed because it is too large
Load diff
28
2024/haskell/resources/day5_example.txt
Normal file
28
2024/haskell/resources/day5_example.txt
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
47|53
|
||||||
|
97|13
|
||||||
|
97|61
|
||||||
|
97|47
|
||||||
|
75|29
|
||||||
|
61|13
|
||||||
|
75|53
|
||||||
|
29|13
|
||||||
|
97|29
|
||||||
|
53|29
|
||||||
|
61|53
|
||||||
|
97|53
|
||||||
|
61|29
|
||||||
|
47|13
|
||||||
|
75|47
|
||||||
|
97|75
|
||||||
|
47|61
|
||||||
|
75|61
|
||||||
|
47|29
|
||||||
|
75|13
|
||||||
|
53|13
|
||||||
|
|
||||||
|
75,47,61,53,29
|
||||||
|
97,61,53,29,13
|
||||||
|
75,29,13
|
||||||
|
75,97,47,61,53
|
||||||
|
61,13,29
|
||||||
|
97,13,75,29,47
|
||||||
|
|
@ -13,12 +13,13 @@ module Lib.Parser
|
||||||
surrounded,
|
surrounded,
|
||||||
parens,
|
parens,
|
||||||
separated,
|
separated,
|
||||||
|
whitespace,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
import Control.Applicative (Alternative (..))
|
import Control.Applicative (Alternative (..))
|
||||||
import Control.Monad (void)
|
import Control.Monad (void)
|
||||||
import Data.Char (isDigit)
|
import Data.Char (isDigit, isSpace)
|
||||||
|
|
||||||
newtype Parser a = Parser
|
newtype Parser a = Parser
|
||||||
{ parse :: String -> Maybe (a, String)
|
{ parse :: String -> Maybe (a, String)
|
||||||
|
|
@ -63,6 +64,9 @@ satisfy predicate = Parser $ \case
|
||||||
| predicate x -> Just (x, xs)
|
| predicate x -> Just (x, xs)
|
||||||
| otherwise -> Nothing
|
| otherwise -> Nothing
|
||||||
|
|
||||||
|
whitespace :: Parser Char
|
||||||
|
whitespace = satisfy isSpace
|
||||||
|
|
||||||
char :: Char -> Parser Char
|
char :: Char -> Parser Char
|
||||||
char c = satisfy (== c)
|
char c = satisfy (== c)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue