Halaman

Kamis, 30 Juni 2011

Additional Range method

class Range
  # return true if 2 range overlapped
  def overlap? other_range
    include?(other_range.begin) || other_range.include?(self.begin)
  end

  # return a new intersection range between two ranges
  def & other_range
    raise TypeError, "exclusive range can't be intersected with non-exclusive one" unless self.exclude_end? == other_range.exclude_end?
    new_begin = [self.begin, other_range.begin].max
    new_end = [self.end, other_range.end].min
    new_begin <= new_end ? Range.new(new_begin, new_end, self.exclude_end?) : nil
  end

  # return true if other_range is a subset in self
  def contains? other_range
    if !exclude_end?
      include?(other_range.begin) && include?(other_range.end)
    elsif self.begin.respond_to?('>=')
      self.begin <= other_range.begin && self.end.send(other_range.exclude_end? ? '>=' : '>', other_range.end)
    else
      raise TypeError, "can't determine inclusion of range with this type of members"
    end
  end

  # return true if self is a subset of other_range
  def within? other_range
    other_range.contains? self
  end

  # return length of the range (only for subtract-able range)
  def length
    self.end.respond_to?('-') ? self.end - self.begin : nil
  end

  # return next range with same span (only for subtract-able and add-able range)
  def succ allow_touch=false
    return nil unless self.end.respond_to?('-') && self.end.respond_to?('+')
    new_begin = allow_touch || exclude_end? || !self.end.respond_to?(:succ) ? self.end : self.end.succ
    new_end = new_begin + length
    Range.new(new_begin, new_end, exclude_end?)
  end

  # return previous range with same span (only for subtract-able and add-able range)
  def pred allow_touch=false
    return nil unless self.end.respond_to?('-') && self.begin.respond_to?('+')
    new_end = allow_touch || exclude_end? || !self.begin.respond_to?(:pred) ? self.begin : self.begin.pred
    new_begin = new_end - length
    Range.new(new_begin, new_end, exclude_end?)
  end
end

Tidak ada komentar:

Posting Komentar