import random

# Generates random intervals whose endpoints are in the range 0 through m (inclusive).
# The endpoints are reals and it is guaranteed that the right endpoint of each interval
# is at least as large as the left endpoint
def generateIntervals(n, m):
  I = []
  for i in range(0, n):
    x = []
    x.append(random.uniform(0, m))
    x.append(random.uniform(x[0], m))
    I.append(x)

  return I

# Calculates the length or span of an interval.
# Assumes that the right endpoint is at least as large as the left endpoint
def span(x):
  return x[1] - x[0]

# Returns true if x and y overlap
def overlap(x, y):
  if(x[0] <= y[0]):
    return (x[0] < y[0] < x[1])
  else:
    return (y[0] < x[0] < y[1])

# Returns the index of an interval in I with smallest span
def getMinSpanInterval(I):

  minSpanIndex = 0
  minSpan = I[0][1] - I[0][0]
  for i in range(1, len(I)):
    if(span(I[i]) < minSpan):
      minSpanIndex = i
      minSpan = span(I[i])

  return minSpanIndex

# Returns a subset of non-overlapping intervals obtaining by running the
# GREEDY_SPAN algorithm
def greedySpan(I):
  S = []

  # Repeatedly perform greedy step until no more requests are left
  # to process
  while(len(I) > 0):

    # Pick the interval from I with smallest span, delete from I and add to S
    i = getMinSpanInterval(I)
    y = I.pop(i)
    S.append(y)

    # Delete from I all intervals that overlap with the chosen interval
    # After this loop J will contain indices of intervals that overlap with y
    J = []
    for i in range(0, len(I)):
      if(overlap(I[i], y)):
        J.append(i)
	
    # Intervals with these indices are deleted from I
    # Note that indices are processed in decreasing order
    for i in range(len(J)-1, -1, -1):
      I.pop(J[i])

  return S

# Returns the degree of an interval x with respect to a set of intervals I
def degree(x, I):
  deg = 0

  # Scan all the intervals in I and count
  # 1 for every interval that overlaps x
  for y in I:
    if(overlap(x, y)):
      deg = deg + 1

  return deg - 1

# Returns the index of an interval in I with smallest degree
def getMinDegreeInterval(I):

  minDegreeIndex = 0
  minDegree = degree(I[0], I)

  for i in range(1, len(I)):
    if(degree(I[i], I) < minDegree):
      minDegreeIndex = i
      minDegree = degree(I[i], I)

  return minDegreeIndex


# Returns a subset of non-overlapping intervals obtaining by running the
# GREEDY_DEGREE algorithm
def greedyDegree(I):
  S = []

  # Repeatedly perform greedy step until no more requests are left
  # to process
  while(len(I) > 0):

    # Pick the interval from I with smallest span, delete from I and add to S
    i = getMinDegreeInterval(I)
    y = I.pop(i)
    S.append(y)

    # Delete from I all intervals that overlap with the chosen interval
    # After this loop J will contain indices of intervals that overlap with y
    J = []
    for i in range(0, len(I)):
      if(overlap(I[i], y)):
        J.append(i)

    # Intervals with these indices are deleted from I
    # Note that indices are processed in decreasing order
    for i in range(len(J)-1, -1, -1):
      I.pop(J[i])

  return S
