this repo has no description
1module Lib
2 ( parsePipes
3 , getGroup
4 , countGroups
5 ) where
6
7import Data.List.Split (splitOn)
8import Data.List (foldl', nub, (\\))
9import qualified Data.Map.Strict as M
10
11parsePipes :: [String] -> M.Map Int [Int]
12parsePipes = foldl' updateConnMap M.empty
13
14updateConnMap :: M.Map Int [Int] -> String -> M.Map Int [Int]
15updateConnMap m s = M.insert program connections m
16 where program = read (head $ words s) :: Int
17 connectionStrs = splitOn ", " . head . tail . splitOn " <-> " $ s
18 connections = map (\cstr -> read cstr :: Int) connectionStrs
19
20getGroup :: Int -> M.Map Int [Int] -> [Int]
21getGroup p = go [p]
22 where go :: [Int] -> M.Map Int [Int] -> [Int]
23 go group m =
24 let conns = nub . concatMap (\p' -> case M.lookup p' m of
25 Just ps -> ps
26 Nothing -> []
27 ) $ group
28 in if (conns \\ group) == [] then group
29 else go (nub $ group ++ conns) m
30
31countGroups :: M.Map Int [Int] -> Int
32countGroups m = let firstGroup = getGroup 0 m
33 in go [firstGroup] (removePrograms firstGroup m) 1
34 where go :: [[Int]] -> M.Map Int [Int] -> Int -> Int
35 go groups m' count
36 | m' == M.empty = count
37 | otherwise = go (groups ++ [nextGroup]) (removePrograms nextGroup m') (count + 1)
38 where nextGroup = getGroup (fst . head . take 1 . M.toAscList $ m') m'
39
40removePrograms :: [Int] -> M.Map Int [Int] -> M.Map Int [Int]
41removePrograms [] m = m
42removePrograms (p:ps) m = removePrograms ps $ M.delete p m