Method: FatCore::Range#gaps

Defined in:
lib/fat_core/range.rb

#gaps(ranges) ⇒ Array<Range>

If this range is not spanned by the ranges collectively, return an Array of ranges representing the gaps in coverage. The ranges can over-cover this range on the left or right without affecting the result, that is, each range in the returned array of gap ranges will always be subsets of this range.

If the ranges span this range, return an empty array.

Examples:

(0..10).gaps([(0..3), (5..6), (9..10)])  #=> [(4..4), (7..8)]
(0..10).gaps([(-4..3), (5..6), (9..15)]) #=> [(4..4), (7..8)]
(0..10).gaps([(-4..3), (4..6), (7..15)]) #=> [] ranges span this one
(0..10).gaps([(-4..-3), (11..16), (17..25)]) #=> [(0..10)] no overlap
(0..10).gaps([])                             #=> [(0..10)] no overlap

Parameters:

Returns:

[View source]

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/fat_core/range.rb', line 53

def gaps(ranges)
  if ranges.empty?
    [clone]
  elsif spanned_by?(ranges)
    []
  else
    # TODO: does not work unless min and max respond to :succ
    ranges = ranges.sort_by(&:min)
    gaps = []
    cur_point = min
    ranges.each do |rr|
      break if rr.min > max
      if rr.min > cur_point
        start_point = cur_point
        end_point = rr.min.pred
        gaps << (start_point..end_point)
        cur_point = rr.max.succ
      elsif rr.max >= cur_point
        cur_point = rr.max.succ
      end
    end
    gaps << (cur_point..max) if cur_point <= max
    gaps
  end
end