diff options
author | Tom Smeding <tom@tomsmeding.com> | 2024-12-06 09:27:31 +0100 |
---|---|---|
committer | Tom Smeding <tom@tomsmeding.com> | 2024-12-06 09:27:31 +0100 |
commit | bdda4fc3382106b9d98117a864b72d6ceaab779f (patch) | |
tree | f467b422a45ffce7da6a27847056b26c391b393c /2024 | |
parent | 9fe655704e5dd35c988ea9bca34ed94f3a6ab8d2 (diff) |
5 (don't put f*** cycles in your graph)
Diffstat (limited to '2024')
-rw-r--r-- | 2024/5.hs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/2024/5.hs b/2024/5.hs new file mode 100644 index 0000000..6c72b95 --- /dev/null +++ b/2024/5.hs @@ -0,0 +1,50 @@ +{-# LANGUAGE MultiWayIf #-} +{-# OPTIONS -Wno-incomplete-uni-patterns #-} +import Data.List (tails, find, sortBy) +import Data.Maybe (isNothing, mapMaybe) +import qualified Data.Set as Set +import qualified Data.Map.Strict as Map +import Control.Monad (forM_) + +splitOn :: Eq a => a -> [a] -> [[a]] +splitOn _ [] = [[]] +splitOn sep (x:xs) | x == sep = [] : splitOn sep xs + | otherwise = let l = splitOn sep xs in (x : head l) : tail l + +main :: IO () +main = do + (rules', _ : seqs') <- break null . lines <$> getContents + let rules = map (\s -> let (a, _:b) = break (=='|') s in (read @Int a, read @Int b)) rules' + let seqs = map (map (read @Int) . splitOn ',') seqs' + let pairsOf l = concatMap (\(x:xs) -> map (x,) xs) (init (tails l)) + let validPair (a, b) = isNothing (find (== (b, a)) rules) + let validSeq = all validPair . pairsOf + let middle l = l !! (length l `div` 2) + print $ sum [middle l | l <- seqs, validSeq l] + + let lookups x = map snd . filter ((== x) . fst) + cmp a b = + let na = lookups a rules + nb = lookups b rules + in if | b `elem` na -> LT + | a `elem` nb -> GT + | otherwise -> EQ + print $ sum . map (\l -> if validSeq l then 0 else middle (sortBy cmp l)) $ seqs + + -- let postSet = \start -> go mempty (Map.singleton start []) + -- where go seen fringe = + -- let news = Map.fromList (mapMaybe (\(a,b) -> case Map.lookup a fringe of Just hist -> Just (b, a:hist) ; Nothing -> Nothing) rules) + -- Map.\\ seen + -- in if Map.null news then seen else go (seen <> news) news + -- cmp a b | a == b = EQ + -- | b `Map.member` postSet a = LT + -- | a `Map.member` postSet b = GT + -- | otherwise = error $ "Cannot compare: " ++ show a ++ " and " ++ show b + -- let allnums = Set.toList (Set.fromList (map fst rules ++ map snd rules)) + -- forM_ allnums $ \n -> do + -- putStrLn $ "post: " ++ show n ++ " -> " ++ show (Map.toList (postSet n)) ++ " (" ++ show (Map.keys (postSet n) == allnums) ++ ")" + -- -- forM_ seqs $ \l -> do + -- -- if validSeq l + -- -- then putStrLn $ "valid: " ++ show l + -- -- else putStrLn $ "sort " ++ show l ++ " -> " ++ show (sortBy cmp l) + -- print $ sum . map (\l -> if validSeq l then 0 else middle (sortBy cmp l)) $ seqs |