Finding integer distance between two intervals

Question:

I’m looking for an easy way to find the minimum distance between two integer intervals using python. For example, the minimum between [0,10] and [12,20] would be 2. If the two intervals overlap in any way, the distance would be 0.

Any suggestions on an easy way to do this? I can’t help but think there must be a clean, ‘pythonic’ way to get at this question.

Asked By: David M

||

Answers:

def solve(r1, r2):
     # sort the two ranges such that the range with smaller first element
     # is assigned to x and the bigger one is assigned to y
     x, y = sorted((r1, r2))

     #now if x[1] lies between x[0] and y[0](x[1] != y[0] but can be equal to x[0])
     #then the ranges are not overlapping and return the differnce of y[0] and x[1]
     #otherwise return 0 
     if x[0] <= x[1] < y[0] and all( y[0] <= y[1] for y in (r1,r2)):
        return y[0] - x[1]
     return 0
... 
>>> solve([0,10],[12,20])
2
>>> solve([5,10],[1,5])
0
>>> solve([5,10],[1,4])
1
Answered By: Ashwini Chaudhary
dist=min(y)-max(x)
if dist>0:
    return dist
else:
    return 0
Answered By: Wesley Bowman

Hopefully the following helps:

def myDist(a,b):
    if a[0] <= a[1] < b[0]:
        return b[0] - a[1]
    if b[0] <= b[1] < a[0]:
        return a[0] - b[1]
    return 0

Good Luck!!!

Answered By: Nate Kingsley

Doesn’t really depend on the programming language:

if (EndA < StartA || EndB < StartA) # check for malformed intervals
  return 0;
return max(0, StartA - EndB, StartB - EndA)

(This assumes the intervals are closed. If the intervals are open, you need to adjust the check for malformed intervals accordingly.)


The other answers lack justification for their formulas, so let me give one:

Let the two intervals be [startA, endA] and [startB, endB]. The two intervals overlap if

(StartA <= EndB) and (StartB <= EndA)

Since we are only interested in the case where there is no overlap, we take the negation of that condition

(StartA > EndB) or (StartB > EndA)

Now if StartA > EndB, then the first interval lies to the right of the first, so their distance is startA - endB. Conversely, if StartB > EndA, the first lies to the left of the second, so their distance is startB - endA.

Taken together we get

if (StartA > EndB):
  return StartA - EndB
if (StartB > EndA):
  return StartB - EndA
return 0

Now consider that (a) for valid intervals (i.e. EndA >= StartA and EndB >= StartB), either one of StartA - EndB or StartB - EndA will be negative if there is no overlap*, and that (b) for overlapping ranges both StartA - EndB and StartB - EndA will be non-positive**. Then you can shorten this to:

max(0, StartA – EndB, StartB – EndA)

As for invalid intervals: If an interval is invalid and we define that to mean an empty interval, i.e. as an empty set without any elements, and we further define the distance between two intervals as the length of the smallest interval that can be added so that it together with both intervals forms a single continuous interval, then the distance between an invalid interval and another interval is 0 (as the second interval already forms a single continuous interval, so we only need to add an empty interval, which has length 0).


(*) If e.g. the first interval lies to the right of the second, it follows that

StartA > EndB // assuming first interval lies to the right of the second
EndA >= StartA // assuming first interval is valid
EndB >= StartB // assuming first interval is valid

EndA >= StartA > EndB >= StartB // combine the inequalities
EndA > StartB // shorten
StartB - EndA < 0 // so the other quantity is negative

(**) Since for overlapping ranges we have StartA <= EndB and StartB <= EndA, it follows that StartA - EndB <= 0 and StartB - EndA <= 0

Answered By: blutorange
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.