Module: FatCore::Range
Defined Under Namespace
Modules: ClassMethods
Operations collapse
-
#difference(other) ⇒ Object
(also: #-)
The difference method, -, removes the overlapping part of the other argument from self.
-
#gaps(ranges) ⇒ Array<Range>
If this range is not spanned by the
ranges
collectively, return an Array of ranges representing the gaps in coverage. -
#intersection(other) ⇒ Range?
(also: #&)
Return a Range that represents the intersection between this range and the
other
range. -
#join(other) ⇒ Range?
Return a range that concatenates this range with other if it is contiguous with this range on the left or right; return nil if the ranges are not contiguous.
-
#overlaps(ranges) ⇒ Array<Range>
Within this range return an Array of Ranges representing the overlaps among the given Array of Ranges
ranges
. -
#tex_quote ⇒ String
Allow erb or erubis documents to directly interpolate a Range.
-
#union(other) ⇒ Range?
(also: #+)
Return a Range that represents the union between this range and the
other
range.
Queries collapse
-
#contiguous?(other) ⇒ Boolean
Is self contiguous to other either on the left or on the right? First, the two ranges are sorted by their min values, and the range with the lowest min value is considered to be on the "left" and the other range on the "right".
-
#left_contiguous?(other) ⇒ Boolean
Is self on the left of and contiguous to other? Whether one range is "contiguous" to another has two cases:.
-
#overlaps?(other) ⇒ Boolean
Return whether self overlaps with other Range.
-
#overlaps_among?(ranges) ⇒ Boolean
Return whether any of the
ranges
that overlap self have overlaps among one another. -
#proper_subset_of?(other) ⇒ Boolean
Return whether self is contained within
other
range, without their boundaries touching. -
#proper_superset_of?(other) ⇒ Boolean
Return whether self contains
other
range, without their boundaries touching. -
#right_contiguous?(other) ⇒ Boolean
Is self on the right of and contiguous to other? Whether one range is "contiguous" to another has two cases:.
-
#spanned_by?(ranges) ⇒ Boolean
Return true if the given ranges collectively cover this range without overlaps and without gaps.
-
#subset_of?(other) ⇒ Boolean
Return whether self is contained within
other
range, even if their boundaries touch. -
#superset_of?(other) ⇒ Boolean
Return whether self contains
other
range, even if their boundaries touch.
Sorting collapse
-
#<=>(other) ⇒ -1, ...
Compare this range with other first by min values, then by max values.
Instance Method Details
permalink #<=>(other) ⇒ -1, ...
Compare this range with other first by min values, then by max values.
This causes a sort of Ranges with Comparable elements to sort from left to right on the number line, then for Ranges that start on the same number, from smallest to largest.
367 368 369 |
# File 'lib/fat_core/range.rb', line 367 def <=>(other) [min, max] <=> [other.min, other.max] end |
permalink #contiguous?(other) ⇒ Boolean
Is self contiguous to other either on the left or on the right? First, the two ranges are sorted by their min values, and the range with the lowest min value is considered to be on the "left" and the other range on the "right". Whether one range is "contiguous" to another then has two cases:
- If the max element of the Range on the left respond to the #succ method (that is, its value is a discrete value such as Integer or Date) test whether the succ to the max value of the Range on the left is equal to the min value of the Range on the right.
- If the max element of the Range on the left does not respond to the #succ method (that is, its values are continuous values such as Floats) test whether the max value of the Range on the left is equal to the min value of the Range on the right
265 266 267 |
# File 'lib/fat_core/range.rb', line 265 def contiguous?(other) left_contiguous?(other) || right_contiguous?(other) end |
permalink #difference(other) ⇒ Object Also known as: -
The difference method, -, removes the overlapping part of the other argument from self. Because in the case where self is a superset of the other range, this will result in the difference being two non-contiguous ranges, this returns an array of ranges. If there is no overlap or if self is a subset of the other range, return an array of self
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/fat_core/range.rb', line 154 def difference(other) unless max.respond_to?(:succ) && min.respond_to?(:pred) && other.max.respond_to?(:succ) && other.min.respond_to?(:pred) raise 'Range difference requires objects have pred and succ methods' end if subset_of?(other) # (4..7) - (0..10) [] elsif proper_superset_of?(other) # (4..7) - (5..5) -> [(4..4), (6..7)] [(min..other.min.pred), (other.max.succ..max)] elsif overlaps?(other) && other.min <= min # (4..7) - (2..5) -> (6..7) [(other.max.succ..max)] elsif overlaps?(other) && other.max >= max # (4..7) - (6..10) -> (4..5) [(min..other.min.pred)] else [self] end end |
permalink #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.
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 |
permalink #intersection(other) ⇒ Range? Also known as: &
Return a Range that represents the intersection between this range and the
other
range. If there is no intersection, return nil.
126 127 128 129 |
# File 'lib/fat_core/range.rb', line 126 def intersection(other) return nil unless overlaps?(other) ([min, other.min].max..[max, other.max].min) end |
permalink #join(other) ⇒ Range?
Return a range that concatenates this range with other if it is contiguous with this range on the left or right; return nil if the ranges are not contiguous.
28 29 30 31 32 33 34 |
# File 'lib/fat_core/range.rb', line 28 def join(other) if left_contiguous?(other) ::Range.new(min, other.max) elsif right_contiguous?(other) ::Range.new(other.min, max) end end |
permalink #left_contiguous?(other) ⇒ Boolean
Is self on the left of and contiguous to other? Whether one range is "contiguous" to another has two cases:
- If the elements of the Range on the left respond to the #succ method (that is, its values are discrete values such as Integers or Dates) test whether the succ to the max value of the Range on the left is equal to the min value of the Range on the right.
- If the elements of the Range on the left do not respond to the #succ method (that is, its values are continuous values such as Floats) test whether the max value of the Range on the left is equal to the min value of the Range on the right
206 207 208 209 210 211 212 |
# File 'lib/fat_core/range.rb', line 206 def left_contiguous?(other) if max.respond_to?(:succ) max.succ == other.min else max == other.min end end |
permalink #overlaps(ranges) ⇒ Array<Range>
Within this range return an Array of Ranges representing the overlaps
among the given Array of Ranges ranges
. If there are no overlaps, return
an empty array. Don't consider overlaps in the ranges
that occur outside
of self.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/fat_core/range.rb', line 89 def overlaps(ranges) if ranges.empty? || spanned_by?(ranges) [] else ranges = ranges.sort_by(&:min) overlaps = [] cur_point = nil ranges.each do |rr| # Skip ranges outside of self next if rr.max < min || rr.min > max # Initialize cur_point to max of first range if cur_point.nil? cur_point = rr.max next end # We are on the second or later range if rr.min < cur_point start_point = rr.min end_point = cur_point overlaps << (start_point..end_point) end cur_point = rr.max end overlaps end end |
permalink #overlaps?(other) ⇒ Boolean
Return whether self overlaps with other Range.
309 310 311 312 |
# File 'lib/fat_core/range.rb', line 309 def overlaps?(other) (cover?(other.min) || cover?(other.max) || other.cover?(min) || other.cover?(max)) end |
permalink #overlaps_among?(ranges) ⇒ Boolean
Return whether any of the ranges
that overlap self have overlaps among one
another.
This does the same thing as Range.overlaps_among?
, except that it filters
the ranges
to only those overlapping self before testing for overlaps
among them.
323 324 325 326 |
# File 'lib/fat_core/range.rb', line 323 def overlaps_among?(ranges) iranges = ranges.select { |r| overlaps?(r) } ::Range.overlaps_among?(iranges) end |
permalink #proper_subset_of?(other) ⇒ Boolean
Return whether self is contained within other
range, without their
boundaries touching.
283 284 285 |
# File 'lib/fat_core/range.rb', line 283 def proper_subset_of?(other) min > other.min && max < other.max end |
permalink #proper_superset_of?(other) ⇒ Boolean
Return whether self contains other
range, without their
boundaries touching.
301 302 303 |
# File 'lib/fat_core/range.rb', line 301 def proper_superset_of?(other) min < other.min && max > other.max end |
permalink #right_contiguous?(other) ⇒ Boolean
Is self on the right of and contiguous to other? Whether one range is "contiguous" to another has two cases:
- If the elements of the Range on the left respond to the #succ method (that is, its values are discrete values such as Integers or Dates) test whether the succ to the max value of the Range on the left is equal to the min value of the Range on the right.
- If the elements of the Range on the left do not respond to the #succ method (that is, its values are continuous values such as Floats) test whether the max value of the Range on the left is equal to the min value of the Range on the right
234 235 236 237 238 239 240 |
# File 'lib/fat_core/range.rb', line 234 def right_contiguous?(other) if other.max.respond_to?(:succ) other.max.succ == min else other.max == min end end |
permalink #spanned_by?(ranges) ⇒ Boolean
Return true if the given ranges collectively cover this range without overlaps and without gaps.
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'lib/fat_core/range.rb', line 333 def spanned_by?(ranges) joined_range = nil ranges.sort.each do |r| unless joined_range joined_range = r next end joined_range = joined_range.join(r) break if joined_range.nil? end if !joined_range.nil? joined_range.min <= min && joined_range.max >= max else false end end |
permalink #subset_of?(other) ⇒ Boolean
Return whether self is contained within other
range, even if their
boundaries touch.
274 275 276 |
# File 'lib/fat_core/range.rb', line 274 def subset_of?(other) min >= other.min && max <= other.max end |
permalink #superset_of?(other) ⇒ Boolean
Return whether self contains other
range, even if their
boundaries touch.
292 293 294 |
# File 'lib/fat_core/range.rb', line 292 def superset_of?(other) min <= other.min && max >= other.max end |
permalink #tex_quote ⇒ String
Allow erb or erubis documents to directly interpolate a Range.
180 181 182 |
# File 'lib/fat_core/range.rb', line 180 def tex_quote to_s end |
permalink #union(other) ⇒ Range? Also known as: +
Return a Range that represents the union between this range and the
other
range. If there is no overlap and self is not contiguous with
other
, return nil
.
143 144 145 146 |
# File 'lib/fat_core/range.rb', line 143 def union(other) return nil unless overlaps?(other) || contiguous?(other) ([min, other.min].min..[max, other.max].max) end |