module Prune ( prune , Compare , cmpName , cmpSize , cmpStdDev ) where import Data.Text (Text) import Data.List (foldl', sortBy) import Data.Ord (comparing) import Data.Map.Strict (Map, toList, fromList) type Compare a = a -> a -> Ordering cmpName, cmpSize, cmpStdDev :: (Compare (Text, (Double, Double)), Compare (Text, (Double, Double))) cmpName = (cmpNameAscending, cmpNameDescending) cmpSize = (cmpSizeDescending, cmpSizeAscending) cmpStdDev = (cmpStdDevDescending, cmpStdDevAscending) cmpNameAscending, cmpNameDescending, cmpStdDevAscending, cmpStdDevDescending, cmpSizeAscending, cmpSizeDescending :: Compare (Text, (Double, Double)) cmpNameAscending = comparing fst cmpNameDescending = flip cmpNameAscending cmpStdDevAscending = comparing (snd . snd) cmpStdDevDescending = flip cmpStdDevAscending cmpSizeAscending = comparing (fst . snd) cmpSizeDescending = flip cmpSizeAscending prune :: Compare (Text, (Double, Double)) -> Double -> Int -> Map Text (Double, Double) -> Map Text Int prune cmp tracePercent nBands ts = let ccTotals = sortBy cmpSizeDescending (toList ts) sizes = map (fst . snd) ccTotals total = sum' sizes limit = (1 - tracePercent / 100) * total bigs = takeWhile (< limit) . scanl (+) 0 $ sizes bands = zipWith const ccTotals $ take nBands bigs ccs = map fst (sortBy cmp bands) in fromList (reverse ccs `zip` [1 ..]) sum' :: [Double] -> Double sum' = foldl' (+) 0