0

In the post find all combinations with non-overlapped regions (code pasted below), the function is given a set of tuples and it recursively finds every possible collection of tuples with non-overlapping values. On the list of tuples T = [(0.0, 2.0), (0.0, 4.0), (2.5, 4.5), (2.0, 5.75), (2.0, 4.0), (6.0, 7.25)], for example, we get

def nonovl(l, idx, right, ll):
    if idx == len(l):
        if ll:
            print(ll)
        return

    next = idx + 1  
    while next < len(l) and right >= l[next][0]:
        next += 1
    nonovl(l, next, right, ll)

    next = idx + 1
    right = l[idx][1]
    while next < len(l) and right >= l[next][0]:
        next += 1
    nonovl(l, next, right, ll + str(l[idx]))

>>> T = [(0.0, 2.0), (0.0, 4.0), (2.5, 4.5), (2.0, 5.75), (2.0, 4.0), (6.0, 7.25)]
>>> l.sort()
>>> nonovl(l, 0, -1, "")
(6.0, 7.25)
(2.5, 4.5)
(2.5, 4.5)(6.0, 7.25)
(2.0, 5.75)
(2.0, 5.75)(6.0, 7.25)
(2.0, 4.0)
(2.0, 4.0)(6.0, 7.25)
(0.0, 4.0)
(0.0, 4.0)(6.0, 7.25)
(0.0, 2.0)
(0.0, 2.0)(6.0, 7.25)
(0.0, 2.0)(2.5, 4.5)
(0.0, 2.0)(2.5, 4.5)(6.0, 7.25)

How might we modify the nonovl() function so that it also allows for combinations that overlap by the start and end values of two tuples? Running it on the same list, for example, we would also get:

(0.0, 2.0)(2.0, 4.0)(6.0, 7.25)
loki
  • 976
  • 1
  • 10
  • 22
Luke Poeppel
  • 143
  • 1
  • 10

1 Answers1

1

Change >= to >. Right now, the code skips over the "next" tuple if the left index value of the "next" tuple is less than or equal to the right index value of the "current" tuple. It finds the first tuple that has a left index value that is strictly greater than the current tuple's right index value.

def nonovl(l, idx, right, ll):
    if idx == len(l):
        if ll:
            print(ll)
        return

    next = idx + 1  
    while next < len(l) and right > l[next][0]:
        next += 1
    nonovl(l, next, right, ll)

    next = idx + 1
    right = l[idx][1]
    while next < len(l) and right > l[next][0]:
        next += 1
    nonovl(l, next, right, ll + str(l[idx]))

Output:

(6.0, 7.25)
(2.5, 4.5)
(2.5, 4.5)(6.0, 7.25)
(2.0, 5.75)
(2.0, 5.75)(6.0, 7.25)
(2.0, 4.0)
(2.0, 4.0)(6.0, 7.25)
(0.0, 4.0)
(0.0, 4.0)(6.0, 7.25)
(0.0, 2.0)
(0.0, 2.0)(6.0, 7.25)
(0.0, 2.0)(2.5, 4.5)
(0.0, 2.0)(2.5, 4.5)(6.0, 7.25)
(0.0, 2.0)(2.0, 5.75)
(0.0, 2.0)(2.0, 5.75)(6.0, 7.25)
(0.0, 2.0)(2.0, 4.0)
(0.0, 2.0)(2.0, 4.0)(6.0, 7.25)
Lapis Rose
  • 644
  • 3
  • 15
  • Thanks! Is there a way to change it further so that these outputs could made into a list of one or more tuples instead of printing in string format? With the above data, the result would be ```[[(6.0, 7.25)], [(2.5, 4.5)], [(2.5, 4.5), (6.0, 7.25)], ..., [(0.0, 2.0), (2.0, 4.0), (6.0, 7.25)]]```. I don't have much experience with recursion and I'm getting all sorts of errors when trying to append each step to a list. – Luke Poeppel Jan 24 '20 at 13:32
  • My question in the comment above seemed a bit complicated, so I made it a separate question here: https://stackoverflow.com/questions/59901396/modify-for-list-output-in-recursion – Luke Poeppel Jan 24 '20 at 19:37
  • It's not too big of a change. What you can do is create an empty list outside and fill it in instead of printing. I'll elaborate more as an answer in your other page. – Lapis Rose Jan 24 '20 at 21:59