0

my current solution is like this:

(A.startAt in B.startAt..B.endAt) || 
    (A.endAt in B.startAt..B.endAt) || 
    (A.startAt <= B.startAt && A.endAt >= B.endAt)

if there is more idiomatic or performant check, please help me.

MozenRath
  • 9,652
  • 13
  • 61
  • 104

3 Answers3

4

How about max(A.startAt,B.startAt)<=min(A.endAt,B.endAt)

Chamod
  • 587
  • 2
  • 6
  • 17
2

The most elegant (in my subjective opinion) is probably

val overlap = a.intersect(b).isNotEmpty()

Or you could do

a.any { b.contains(it) }
// or a.any(b::contains)

which should avoid creating a new collection (which intersect does) - I feel like it's less immediately obvious what it's doing though, the first one reads better to me.


You could manually work out if the start or end of one range is between the start and end of the other, which is probably the "most efficient" way - that can be a little tricky though because you can have descending ranges, which aren't IntRanges, they're just IntProgressions (which an IntRange is a subclass of). So you'd have to do this kind of thing:

fun overlap(a: IntProgression, b: IntProgression): Boolean {
    val max = maxOf(a.first, a.last)
    val min = minOf(a.first, a.last)
    return (b.first >= min && b.first <= max) || (b.last >= min && b.last <= max)
}

and I mean, is it really worth it? (Maybe it is! But you should benchmark it if so, because you're adding complexity and there should be a concrete benefit to that tradeoff)

cactustictacs
  • 17,935
  • 2
  • 14
  • 25
  • Won't the `any()` solution perform badly? – gidds Jun 18 '22 at 09:55
  • @gidds depends! It's inefficient (*O(n)*), but it should just be iterators vs creating collections of all the elements in a range, so it's a time vs memory tradeoff. The function is the most efficient, but it's the most complex/least "idiomatic". I just like to give people options when the question asks something like "what's the most efficient and also most elegant/idiomatic approach" because those are often mutually exclusive things, and they'll have to decide which is more important to them. (I wouldn't use the `any` one myself personally, but it's good to know you *could* I think!) – cactustictacs Jun 18 '22 at 18:49
  • this is the best answer for sure – Brooks DuBois Dec 15 '22 at 22:57
0
B.endAt >= A.startAt && B.startAt <= A.endAt
lukas.j
  • 6,453
  • 2
  • 5
  • 24