2011-03-10 60 views
4

我有时间跨度(表示为整数元组)名单确定的时间间隔,如:从时间跨度的名单(不包括在列表中的跨度)

timespans = [ (1200, 1210) 
     , (1202, 1209) 
     , (1505, 1900) 
     , (1300, 1500) 
     , (1400, 1430) 
     ] 

我想找到一个优雅的Haskell解决方案来确定时间间隔,而时间间隔不在列表中。

回答

4

首先我会按照他们的开始时间对跨度进行排序。然后你可以很容易地合并重叠的跨度。一旦你有了,你可以通过迭代合并跨度(通过拖拽它的尾部)来找到差距。差距将是从第一个项目的结束时间到第二个项目的开始时间的跨度。

在这段代码应该是这样的:

mergeSortedSpans [] = [] 
mergeSortedSpans ((from1, to1):(from2, to2):spans) | to1 >= from2 = 
    mergeSortedSpans $ (from1, max to1 to2):spans 
mergeSortedSpans (span:spans) = span : mergeSortedSpans spans 

inPairs _ [] = [] 
inPairs f (x:xs) = zipWith f (x:xs) xs 

gap (_, to1) (from2, _) = (to1, from2) 

gaps = inPairs gap . mergeSortedSpans . sort 

用法:

gaps timespans 
-- [(100,500),(1210,1300),(1500,1505)] 
3

我的解决方案与分而治之的作品融化所有重叠的时间跨度,以获得非重叠时间跨度的排序列表:

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) 

它没有那清新典雅我希望这将是。 ..任何人有一个更短的解决方案呢?

2

感谢sepp2k - 您的权利;它更容易你建议的方式!在工作哈斯克尔码:

flattentime :: [(Integer,Integer)] -> [(Integer,Integer)] 
flattentime [] = [] 
flattentime [x] = [x] 
flattentime ((x1,x2):(y1,y2):ts) | y2<x2 = (x1,x2):(flattentime ts) 
           | y1<x2 = (x1,y2):(flattentime ts) 
           | otherwise = (x1,x2) : (flattentime ((y1,y2):ts)) 

以后我就只要致电:

> (flattentime.sort) timespans 
3

优雅 - 你的意思是什么样的?

import Data.List 
timespans = [ (1200, 1210) 
     , (1202, 1209) 
     , (1505, 1900) 
     , (1300, 1500) 
     , (1400, 1430) 
     ] 

gaps xs0 = filter g $ zipWith f xs (tail xs) where 
    xs = merge $ sort xs0 
    f (_, t0) (t1, _) = (t0, t1) 
    g (t0, t1) = t0 < t1 
    merge [] = [] 
    merge ((t0, t1):(t2, t3):ys) | t2 < t1 = merge ((t0, max t1 t3) : ys) 
    merge (y:ys) = y : merge ys 

main = print (gaps timespans)