Range does not take an Range object

Range#include? does not take a Range object. It is strange for me.

And, I want Range#insersect?(aRange) method.

greentea@fa.so-net.ne.jp

class Range
alias_method :old_include?, :include?

def include?(obj)
    if obj.is_a? Range
        old_include? obj.first and
        old_include? obj.last
    else
        old_include? obj
    end
end

def intersect?(aRange)
    aRange.each do |i|
        return true if include? i
    end
   
    false
end

end

p (1…4).include? 2…3

p (1…4).include? 1…4

p (1…6).intersect? 4…8

p (1…6).intersect? 6…8

I am happy that there were at least three persons (included me) who
implemented Range#include? or intersect? incorrectly in the
world. And, interestingly, each person implement them in different
way.

It seems valuable that include? and intersect? are built-in.

greentea2fa2.so-net.ne.jp

class Range
alias_method :original_include?, :include?

def include?(other)
return original_include?(other) unless other.is_a?(Range)
return other.first >= first && other.last <= last
end

def intersect?(other)
return true if include?(other)
return include?(other.last) || include?(other.first) || other.include?(first) || other.include?(last)
end
end

Oops, that’s slightly broken. Here’s a fix.

class Range
alias_method :old_include?, :include?

def include?(obj)
    if obj.is_a? Range
        old_include? obj.first and
        old_include? obj.exclude_end? ? obj.last-1 : obj.last
    else
        old_include? obj
    end
end

def intersect?(aRange)
    aRange.each do |i|
        return true if include? i
    end
   
    false
end

end

class Range
alias_method :original_include?, :include?

def include?(other)
return original_include?(other) unless other.is_a?(Range)
return other.first >= first && other.last <= last
end

def intersect?(other)
return true if include?(other)
return include?(other.last) || include?(other.first) || other.include?(first) || other.include?(last)
end
end

It should indeed really be built in, because the presence of exclude_end?
and empty ranges make things really complicated. If I could disregard
these issues, I’d implement intersect? as

def intersect?(other)
return last >= other.first && other.last >= first
end

(I had to do that for an assignment in college once, it’s weird but
correct; it basically says self is not all smaller than other, and other
is not all smaller than self.)

But that it’s hard is illustrated by the current implementation itself,
e.g.,

irb(main):001:0> (1…1).max
=> nil
irb(main):002:0> (“1”…“1”).max
=> “1”

which seems inconsistent (the inconsistency is because of an inconsistency
in each). Another funny thing is that

(1…10000000000).member? 9999999999

takes ages to complete, though

(1…10000000000).include? 9999999999

completes immediately. Still member? is a synonym for include?, or at
least Programming Ruby says so. But I guess I’m the only one interested in
numbers like 10000000000 :slight_smile:

Peter

class Range
alias_method :old_include?, :include?

def include?(obj)
    if obj.is_a? Range
        old_include? obj.first and
        old_include? obj.exclude_end? ? obj.last-1 : obj.last
                                          ^^^^^^^^^^

Doesn’t work for ranges like ‘a’…‘z’. If I understand well, the only
requirement for a Range is that it’s elements have <=> and succ as
operations.

    else
        old_include? obj
    end
end

def intersect?(aRange)
    aRange.each do |i|
        return true if include? i
    end

    false
end

end

My solution is below. The include? should be slightly faster since it
calls <=> only twice. The intersect? is also faster for large ranges. Also
it works for ranges where first is larger than last (the program above
says false to ((“e”…“e”).include? (“e”…“e”)) while I think it should
say true (all elements of “e”…“e” are in “e”…“e”, since there are
none). But the original Range isn’t always consistent there either since
(“a”…“a”).each do |i| p i end prints “a” (replace “a” with 0 and it
prints nothing), but (“a”…“a”).include? “a” says false. Anyway, the code
below is probably harder to find bugs in…

Peter

class Range

alias_method :old_include?, :include?

def include?(obj)
if obj.is_a? Range
lb1 = first.succ
ub1 = exclude_end? ? last : last.succ
lb2 = obj.first.succ
ub2 = obj.exclude_end? ? obj.last : obj.last.succ
(((lb2 <=> lb1) >= 0) && ((ub1 <=> ub2) >= 0))
else
old_include? obj
end
end

def intersect?(obj)
lb1 = first.succ
ub1 = exclude_end? ? last : last.succ
lb2 = obj.first.succ
ub2 = obj.exclude_end? ? obj.last : obj.last.succ
if (lb2 <=> ub2) > 0 then
false
elsif (lb1 <=> ub1) > 0
false
else
(((ub1 <=> lb2) >= 0) && ((ub2 <=> lb1) >= 0))
end
end
end

p ((“a”…“e”).include? (“a”…“e”)) # true
p ((“a”…“e”).include? (“a”…“f”)) # false
p ((“a”…“e”).include? (“a”…“f”)) # true
p ((“a”…“e”).include? (“a”…“f”)) # false
p ((“a”…“f”).include? (“a”…“f”)) # true
p ((“e”…“e”).include? (“e”…“e”)) # false
p ((“e”…“e”).include? (“e”…“e”)) # true

p ((“a”…“e”).intersect? (“e”…“i”)) # true
p ((“a”…“e”).intersect? (“e”…“i”)) # false
p ((“a”…“e”).intersect? (“d”…“i”)) # true
p ((“a”…“e”).intersect? (“e”…“e”)) # false

class Range

alias_method :old_include?, :include?

def include?(obj)
if obj.is_a? Range

  #lb1 = first.succ
    lb1 = first
  ub1 = exclude_end? ? last : last.succ
  #lb2 = obj.first.succ
    lb2 = obj.first
···
  ub2 = obj.exclude_end? ? obj.last : obj.last.succ
  (((lb2 <=> lb1) >= 0) && ((ub1 <=> ub2) >= 0))
else
  old_include? obj
end

end

def intersect?(obj)
lb1 = first.succ
ub1 = exclude_end? ? last : last.succ
lb2 = obj.first.succ
ub2 = obj.exclude_end? ? obj.last : obj.last.succ
if (lb2 <=> ub2) > 0 then
false
elsif (lb1 <=> ub1) > 0
false
else
(((ub1 <=> lb2) >= 0) && ((ub2 <=> lb1) >= 0))
end
end
end