Finding overlap of given list - python-3.x

Find overlap which given list, a list of intervals like [2, 4], returns whether any two intervals overlap. Boundary overlaps don't count.
Example:
`>>> check_overlap(li=[[1,5], [8,9], [3,6]])
True
>>> check_overlap(li=[[1,5], [5,6]])
False`
data= [[1, 5], [8, 9], [3, 6]]
values = [[value for value in range(elem[0], elem[1])]for elem in data]
print(values)
[[1, 2, 3, 4], [8], [3, 4, 5]]
After that i want to know how to check with each element in a list whether any two intervals overlapping.

For checking the overlap, I would sort the bigger list with first element of the sublists, and check the 2nd element of a sublist is bigger than the 1st element of the next sublist.
def overlap(li):
li.sort(key=lambda x: x[0])
for i in range(len(li)-1):
if li[i][1] > li[i+1][0]:
return True
return False
print(overlap([[1,5], [8,9], [3,6]]))
print(overlap([[1,5], [5,6]]))
True
False

I would use the itertools.combinations function as such:
from itertools import combinations
def check_overlap(li):
lists = [list(range(a, b)) for a, b in li] # Shorter way of your values = ... line
for l1, l2 in combinations(lists, 2):
if any(l in l2 for l in l1):
return True
return False
The combinations(lists, 2) call gives you all possible unique combinations of different elements.
Next, the any() function takes any iterable and returns True if any of the elements in the iterable are True (or rather 'truthy'). In this case, the l in l2 for l in l1 is a generator expression, but would work the same with square brackets around it to explicitly make it into a list first.

You can create sets and check for intersection -
data= [[1, 5], [8, 9], [3, 6]]
sets_from_data = [set(range(*l)) for l in data]
intersection_exists = bool(max([len(a.intersection(b)) for a in sets_from_data for b in sets_from_data if a != b]) > 0)
intersection_exists
# True

If you only have integers you can indeed use range to do this test:
def check_overlap(li):
ranges = [range(r[0]+1, r[1]-1) for r in li]
return any(any(e-1 in r for r in ranges) for l in li for e in l)
On the other hand, if you have floating point values you'll have to tests both bounds of the interval individually (using < and >):
def is_in_range(value, boundaries):
m, M = boundaries
return value > m+1 and value < M-1
def check_overlap(li):
return any(any(is_in_range(e, r) for r in li) for l in li for e in l)

Related

LIS on two arrays

I feel lost on how to approach this question,
Given two integer array of size 𝑛
, 𝑚
, I want to merge these two arrays into one such that order of element in each array doesn't change and size of their Longest Increasing Subsequence become maximum.
Once we choose an element of A or B, we cannot choose an earlier element of that sequence
My goal is to find maximum possible length of longest increasing subsequence.
This is what I have so far:
def sequences(a, b, start_index=0, min_val=None):
limits = a[start_index], b[start_index]
lower = min(limits)
higher = max(limits)
if min_val is not None and min_val > lower:
lower = min_val
options = range(lower, higher + 1)
is_last = start_index == len(a) - 1
for val in options:
if is_last:
yield [val]
else:
for seq in sequences(a, b, start_index+1, min_val=val+1):
yield [val, *seq]
for seq in sequences([1,3,1,6], [6,5,4,4]):
print(seq)
However, this results in: [1, 3, 4, 5], [1, 3, 4, 6], [2, 3, 4, 5], [2, 3, 4, 6].
The expected output should be:
array1: [1,3,1,6]
array2: [6,5,4,4]
We take 1(from array1), 3(from array1), 4(from array2), 6(from array1)
Giving us LIS: [1,3,4,6].
We got this by not choosing an earlier element from a sequence once we are at a certain value.
How do I stop it from unwanted recursion?

Get element range in list and swap

I want to swap element list by range in python
my code is
List = [1,2,3,4,5,6]
def swap(list_, a, b):
list_[a], list_[b] = list_[b], list_[a]
swap(List, 0, 5,)
print(List)
and my output is
[6, 2, 3, 4, 5, 1]
but what i want is swapped by list index range
# my expected output
n = 2 (add var by input)
#and it swapped to this
[3, 4, 5, 6, 1, 2]
You can use something like this:
def swap(List, n):
return List[n:] + List[:n]
List = [1,2,3,4,5,6]
n = input()
print(swap(List, n))
Using slice (:) you can split your list in sublists by index. Then you can recombine them in the return statement

Reverse operation of torch.unique

In pytorch , unique (with return_count is True) operation do like this
[1,1,2,2,3,3] => ([1,2,3],[2,2,2])
Are there any reverse operations of torch.unique() ?
i.e Given a unique list and its count , return the original list like
([1,2,3],[2,2,2]) = > [1,1,2,2,3,3]
If you include the return inverse parameter it will return the indices for where elements in the original input ended up in the returned unique list. Then you can use take to create a new tensor.
test_tensor = torch.tensor([1,1,2,2,3,3])
items, inverse, counts = test_tensor.unique(return_counts=True, return_inverse=True)
new_tensor = torch.take(items, inverse)
assert new_tensor.eq(test_tensor).all() # true
EDIT:
If you only have a list and the counts this code should give you what you want using repeat. Not sure if a pure pytorch function exists.
test_tensor = torch.tensor([1,1,2,2,3,3])
items, counts = test_tensor.unique(return_counts=True)
new_tensor = torch.tensor([], dtype=torch.int64)
for item, count in zip(items, counts):
new_tensor = torch.cat((new_tensor, item.repeat(count)))
assert new_tensor.eq(test_tensor).all() # true
You probably want torch.repeat_interleave(). You can use it like this:
>>> x = torch.tensor([1, 1, 2, 3, 3, 3])
>>> v, c = torch.unique(x, return_counts=True)
>>> v, c
(tensor([1, 2, 3]), tensor([2, 1, 3]))
>>> torch.repeat_interleave(v, c)
tensor([1, 1, 2, 3, 3, 3])

returing a list of diagonals in square matrices (simplification)

I want to return the diagonals i.e. from left to right and from right to left in a given matrix, Im using list comprehensionsto do so but I came up, in my eyes with a to complicated comprehension that returns the left to right matrix.
I was wondering if there are simpler ways to write a comprehension that returns the right to left diagonal ? Also, given that im a noob, im only beginning to dive into learning the language, i was wondering if the right_left comprehension is even conventional ?
matrix = [[1,2,3],
[4,5,6],
[7,8,9]]
left_right = [arr[i][i]
for i in range(len(arr))]
right_left = [arr[i][[-j
for j in range(-len(arr)+1,1)][i]]
for i in range(-len(arr),0)]
left_right = [arr[i][-(i+1)] for i in range(len(arr))]
For explanation of negiative indicies read this: https://stackoverflow.com/a/11367936/8326775
[list(reversed(matrix[i]))[i] for i in range(len(matrix))]
# more transparent version:
for i in range(len(matrix)):
row = list(reversed(matrix[i]))
el = row[i]
print("reversed row {} = {} -> extract element {} -> gives {}".format(i, row, i, el))
#reversed row 0 = [3, 2, 1] -> extract element 0 -> gives 3
#reversed row 1 = [6, 5, 4] -> extract element 1 -> gives 5
#reversed row 2 = [9, 8, 7] -> extract element 2 -> gives 7
You're probably better off learning about numpy, which has a function for diagonals built-in
>>> import numpy as np
>>> matrix = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
>>> np.diag(matrix)
array([1, 5, 9])
>>> np.diag(matrix, k=1)
array([2, 6])
>>> np.diag(matrix, k=-1)
array([4, 8])

How to get a list of objects by maximum attribute value from N multi-list of objects?

I have a multi-list of objects as follows (simplified version)
listA = [[obj1(val=1),obj2(val=1)],[obj2(val=4),obj3(val=2)]]
listB = [[obj4(val=1),obj5(val=1)],[obj6(val=5),obj7(val=3)]]
listC = [[obj8(val=1),obj9(val=1)],[obj10(val=6),obj11(val=4)]]
I want to get a list of objects from the above multi-list which has the maximum value of a certain attribute by comparing the sub-lists of each multi-list. If the value of the attribute is the same for all the compared objects, it should get any one object.
output:
maxList = [obj1(value=1),obj10(val=6)]
There is a similar question to get object with maximum value of attribute from a list, but this case is for multi-list. I know this can be acheived with nested for loops, but there a must be a better way to do this with itertools and getattr ?
To simplify, let's demonstrate on regular integers. Adapt this approach to your object.
Given
import itertools as it
a = [[1, 1], [3, 2]]
b = [[1, 1], [5, 3]]
c = [[1, 1], [6, 3]]
Code
list(map(max, [list(it.chain(*col)) for col in zip(a, b, c)]))
# [1, 6]
Equivalently
[max([x for x in it.chain(*col)]) for col in zip(a, b, c)]
# [1, 6]

Resources