My solution works with divide-and-conquer to melt all overlapping time slots to get a sorted list of non-overlapping time slots:
module Test where type Time = Int type Start = Time type Stop = Time type Span = (Start, Stop) timespans :: [Span] timespans = [ (1200, 1210) , (1202, 1209) , (1505, 1900) , (1300, 1500) , (1400, 1430) , (500,1200) , (20,100) ] flattentime :: [Span] -> [Span] flattentime [] = [] flattentime [x] = [x] flattentime (s:ss) = combine (flattentime [ times | times <- ss, (fst times) < (fst s) ]) s (flattentime [ times | times <- ss, (fst times) >= (fst s) ]) combine [] s [] = [s] combine [] s ss2 = melt s (head ss2) ++ tail ss2 combine ss1 s [] = firsts ss1 ++ melt (last ss1) s combine ss1 s ss2 = (firsts ss1) ++ melt3 (last ss1) s (head ss2) ++ (tail ss2) melt (x1,x2) (x3,x4) | x2 < x3 = [(x1,x2), (x3,x4)] | x4 < x2 = [(x1,x2)] | otherwise = [(x1,x4)] melt3 (x1,x2) (x3,x4) (x5,x6) = if (length ss >1) then (head ss):(melt y (x5,x6)) else melt y (x5,x6) where ss = melt (x1,x2) (x3,x4) y = last ss firsts [x] = [] firsts [] = [] firsts (x:xs) = x:(firsts xs)
Not so clean and elegant I would like it to be ... who has a shorter solution?
source share