2024 Day 05 in Haskell
This commit is contained in:
		
							parent
							
								
									8719522be0
								
							
						
					
					
						commit
						e6e5da368a
					
				
							
								
								
									
										45
									
								
								2024/day05/day05.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								2024/day05/day05.hs
									
									
									
									
									
										Normal 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
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								aoc.hs
									
									
									
									
									
								
							| @ -60,6 +60,8 @@ starsAndBars 0 b = [replicate (b+1) 0] | ||||
| starsAndBars n 0 = [[n]] | ||||
| 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' kernel x | ||||
|     (a:r0@(b:c:_)) | ||||
| @ -81,3 +83,23 @@ kernelMap' kernel Nothing [_, _] = [] | ||||
| kernelMap :: ([[a]] -> b) -> Maybe a -> [[a]] -> [[b]] | ||||
| kernelMap kernel (Just x) as = kernelMap' kernel (Just x) ((map (const x) (head as)):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 [] | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user