2024 Day 05 in Haskell

This commit is contained in:
germax26 2024-12-06 01:37:11 +11:00
parent 8719522be0
commit e6e5da368a
Signed by: germax26
SSH Key Fingerprint: SHA256:N3w+8798IMWBt7SYH8G1C0iJlIa2HIIcRCXwILT5FvM
2 changed files with 67 additions and 0 deletions

45
2024/day05/day05.hs Normal file
View File

@ -0,0 +1,45 @@
import Aoc
import Data.List.Split ( splitOn )
import Control.Arrow ( second, first )
import Data.List ( nub, partition, sort )
import Data.Maybe ( fromMaybe )
parseFile :: [String] -> ([(Int, [Int])], [[Int]])
parseFile lines =
let
[rules, pages] = splitOn [""] lines
rules' = map (pair . map read . splitOn "|") rules
mentioned = nub $ concatMap unpair rules'
getAll a = map snd $ filter ((==a) . fst) rules'
in
(zip mentioned (map getAll mentioned), map (map read . splitOn ",") pages)
takeMiddle :: [a] -> a
takeMiddle xs = xs !! (length xs `div` 2)
isSafe :: [(Int, [Int])] -> [Int] -> Bool
isSafe rules = fst . foldl isSafe' (True, [])
where
isSafe' (False, prev) _ = (False, prev)
isSafe' (True, prev) a = (fromMaybe True $ not . any (`elem` prev) <$> lookup a rules, a:prev)
part1 :: ([(Int, [Int])], [[Int]]) -> (Int, [[Int]])
part1 (rules, pages) = first (sum . map takeMiddle) $ partition (isSafe rules) pages
part2 :: ([(Int, [Int])], [[Int]]) -> [[Int]] -> Int
part2 (rules, _) = sum . map (takeMiddle . reorder)
where
getPosM rules = memoise $ \values n ->
let ns = fromMaybe [] $ lookup n rules in
if null ns
then (0, values)
else
let (ns', values') = memoMap (getPosM rules) values ns in
(maximum ns' + 1, values')
reorder ns =
let rules' = map (second $ filter (`elem` ns)) $ filter ((`elem` ns) . fst) rules in
map snd $ sort $ zip (unmemo (memoMap $ getPosM rules') ns) ns
main :: IO ()
main = aocMain' parseFile part1 part2

22
aoc.hs
View File

@ -60,6 +60,8 @@ starsAndBars 0 b = [replicate (b+1) 0]
starsAndBars n 0 = [[n]] starsAndBars n 0 = [[n]]
starsAndBars n b = map (0:) (starsAndBars n (b-1)) ++ map (\xs -> head xs + 1 : tail xs) (starsAndBars (n-1) b) starsAndBars n b = map (0:) (starsAndBars n (b-1)) ++ map (\xs -> head xs + 1 : tail xs) (starsAndBars (n-1) b)
-- Kernel
kernelMapRow' :: ([[a]] -> b) -> Maybe a -> [a] -> [a] -> [a] -> [b] kernelMapRow' :: ([[a]] -> b) -> Maybe a -> [a] -> [a] -> [a] -> [b]
kernelMapRow' kernel x kernelMapRow' kernel x
(a:r0@(b:c:_)) (a:r0@(b:c:_))
@ -81,3 +83,23 @@ kernelMap' kernel Nothing [_, _] = []
kernelMap :: ([[a]] -> b) -> Maybe a -> [[a]] -> [[b]] kernelMap :: ([[a]] -> b) -> Maybe a -> [[a]] -> [[b]]
kernelMap kernel (Just x) as = kernelMap' kernel (Just x) ((map (const x) (head as)):as) kernelMap kernel (Just x) as = kernelMap' kernel (Just x) ((map (const x) (head as)):as)
kernelMap kernel Nothing as = kernelMap' kernel Nothing as kernelMap kernel Nothing as = kernelMap' kernel Nothing as
-- Memoisation
type MemoF' a b a' b' = Eq a' => [(a', b')] -> a -> (b, [(a', b')])
type MemoF a b = MemoF' a b a b
memoise :: Eq a => MemoF a b -> MemoF a b
memoise f values a = case lookup a values of
Just b -> (b, values)
Nothing -> let (b, values') = f values a in (b, (a, b):values')
memoMap :: MemoF' a b a' b' -> MemoF' [a] [b] a' b'
memoMap f values [] = ([], values)
memoMap f values (a:as) =
let (b, values') = f values a in
let (bs, values'') = memoMap f values' as in
(b:bs, values'')
unmemo :: Eq a' => MemoF' a b a' b' -> a -> b
unmemo f = fst . f []