python program to find maximal in 2d array - python

I am trying to write program that print maximal points of the input but it is not giving correct output.
Definition of maximal-
Given a set of points P = {p1,p2,...,pn} in 2-space, each represented by its x and y integer coordinates, output the set of the maximal points of P, that is, those points pi, such that pi is not dominated by any other point of P (not both coordinate are dominated)
Example input:
p1(5,7),p2(47,84),p3(89,4),(46,54),(100,1)
Example outut:
p2(47,84),(89,4),(100,1)
The idea of my program is to first sort the point according to x axis then compare the y coordinate.
a=[[5,7],[47,84],[89,4][46,54],[100,1]]
#sort according to x axis
mylist.sort(key=lambda x: x[0])
#compare y coordinate of i to all element right to i
for i in reversed(range(len(a)):
j=i+1
while (j<len(a)):
if(mylist[i][1]>mylist[j][1]):
j+=1
if(j==len(a)):
print(mylist[i])

That's really not how you'd do that in Python. Use language elements that help you express what's going on, that way the code gets more understandable and, as a bonus, more concise. You want to find all elements of a for which no other element of a is greater in both coordinates:
a=[[5,7],[47,84],[89,4],[46,54],[100,1]]
for point in a:
if not any(map(lambda p: p[0] > point[0] and p[1] > point[1], a)):
print(point)
You could also use a list comprehension instead of map, which might be a bit more efficient:
a=[[5,7],[47,84],[89,4],[46,54],[100,1]]
for point in a:
if not any([p[0] > point[0] and p[1] > point[1] for p in a]):
print(point)

Related

Divide and Conquer Approach on 2D Array

I am trying to apply an effective divide and conquer approach on a 2D array that is sorted row-wise, and column-wise. Starting from the bottom left cell in the matrix, my algorithm chooses either to move one cell up or one cell to right depending on whether k is > or < than the curr_cell. However, I keep getting an error of list_indices out of range when I run this code. I'd like some help in debugging this.
The following is my code:
def KeyFinder(k, matrix, x, y):
curr_cell = matrix[x][y] #starting at bottom left corner
if k == curr_cell:
return curr_cell
else:
if curr_cell < k:
KeyFinder(k, matrix, x-1, y) #if target is less than value, it must be above us so move one up
else:
KeyFinder(k, matrix, x, y+1) #otherwise, move one right
var = KeyFinder(20, [[1,4,7,11], [8,9,10,20], [11,12,17,30]], 2, 0)
print(var)
For the error that you see, you have to check the bounds in both direction, not to go out of your matrix.
However, aprart from that your implementation has other issues like when you are calling you function recursively you are not returning the answer.
I did fix it like this:
def KeyFinder(k, matrix, x, y):
m, n = len(matrix) , len(matrix[0]) # get you dimentions
curr_cell = matrix[x][y] #starting at bottom left corner
if k == curr_cell:
return curr_cell
if curr_cell > k and (0 < x) :
return KeyFinder(k, matrix, x-1, y) #if target is less than value, it must be above us so move one up
elif (y < n - 1) :
return KeyFinder(k, matrix, x, y+1) #otherwise, move one right
var = KeyFinder(20, [[1,4,7,11], [8,9,10,20], [11,12,17,30]], 2, 0)
print(var)
I did not change the way you wrote to be easy for you to see the changes, however, when you get the dimension you can as well set the starting point inside the function, not in the call
Ok, lets sum it up quickly. You search for the number 20 in the 3x4 array, it goes like that.
Start at matrix [2][0] = 11.
20>11, so move to [1][0] = 8.
20>8, so move to [0][0] = 1.
20>1, so move to [-1][0]
and there is your mistake, you cant reach index=-1 in an array.

How to find the distance between two elements in a 2D array

Let's say you have the grid:
list = [[-,O,-,-,O,-,],
[O,-,-,-,-,O],
[O,O,-,-,X,-],
[-,-,O,-,-,-]]
How would you get the coordinates of all O's that are within a distance of 3 from X?
From what I saw in other answers, using scipy.spatial.KDTree.query_ball_point seemed like a common approach but I was unable to figure out how to adapt it to my use case. One possible idea I had was to store every coordinate of the list such as
coords=[[0,0],[0,1]...] and then use the scipy method and pass in the coordinate of the X and the searching distance. And then once I received the list of possible coordinates, I then iterate through the list and check which ones are equal to O. I was wondering, however, if there was a more efficient or more optimized solution I could use. Any help would be greatly appreciated.
You don't need to make it too complicate by using Scipy. This problem can easily done by help of mathematics.
Equation of coordinate inside circle is x^2 + y^2 <= Radius^2, so just check coordinate that inside the circle.
list = [[-,O,-,-,O,-,],
[O,-,-,-,-,O],
[O,O,-,-,X,-],
[-,-,O,-,-,-]]
X_coor = #Coordinate of X, in this case y = 2, x = 4
d = #Maximum distance from X in this case d = 3
total = 0
O_coor = [] #Store coordinate of all O near X
for y in range(max(0, X_coor.y - d), min(list.length - 1, X_coor.y + d)):
for x in range(max(0, X_coor.x - sqrt(d**2 - (y - X_coor.y)**2)), min(list.length - 1, X_coor.x + sqrt(d**2 - (y - X_coor.y)**2))):
if list[y][x] == "O":
total++
O_coor.append([x, y])
print(total)
print(O_coor)
It a long code, but you can ask me parts that you don't understand.
Note: This solution check only coordinate in circle area not entire list, so even if you have large list this still very fast.

Does this solution work for the closest pair problem?

I have been looking for the solution for the closest pair problem in Python, but all the solutions were completely different from mine.
Here is the code that finds the closest pair of points on a 2D dimension.
def closest_pair_two_axes(xarr, yarr):
pairs = []
# doesn't really depend if xarr or yarr because the lengths are the same
for i in range(len(xarr)):
pairs.append([xarr[i], yarr[i]])
# Finds the difference between each point
dist_arr = []
for i in range(1, len(pairs)-1):
for j in range(i, len(pairs)):
diff_x = pairs[j][0] - pairs[j - i][0]
diff_y = pairs[j][1] - pairs[j - i][1]
diff = (diff_x ** 2 + diff_y ** 2) ** 0.5
dist_arr.append(round(diff, 2))
index = dist_arr.index(min(dist_arr))
closest_distance = dist_arr[index]
return closest_distance
xarr and yarr are just the names of arrays for the x and y coordinates. In the function, I combine both arrays into a dictionary containing sets of coordinates. After that, I iterate through every possible combination of the coordinates and find the distance between each one of them. In the end, I find the minimum distance, trace it back to the pair it belongs to, and then return it to the user.
This code works but I am not sure if it works correctly and if the result really is the closest pair. Is the code correct?
EDIT:
I changed [j-1] to [j-i] so that it will iterate through every pair possible. Also, I solved the problem using another person's algorithm(the right algorithm) and got the same answer as I did with my algorithm. It might not be the fastest and cleanest code, but it works!

Having trouble with the variant of the "Two Sum" coding challenge?

The two problems seeks to find two elements x and y such that x+y=target. This can be implemented using a brute force approach.
for x in arr:
for y in arr:
if x+y==target:
return [x,y]
We are doing some redundant computation in the for loop -- that is we only want to consider combinations of two elements. We can do a N C 2 dual-loop as follows.
for i, x in enumerate(arr):
if y in arr[i+1:]:
if x+y==target:
return [x,y]
And we save a large constant factor of time complexity. Now let's note that inner most loop is a search. We can either use a hash search or a binary search for.
seen = set()
for i, x in enumerate(arr):
if target-x in seen:
y = target-x
return [x,y]
seen.add(x)
Not that seen is only of length of i. And it will only trigger when hit the second number (because it's complement must be in the set).
A variant of this problem is: to find elements that satisfy the following x-y = target. It's a simple variant but it adds a bit of logical complexity to this problem.
My question is: why does the following not work? That is, we're just modifying the previous code?
seen = set()
for i, x in enumerate(arr):
for x-target in seen:
y = x-target
return [x,y]
seen.add(x)
I've asked a friend, however I didn't understand him. He said that subtraction isn't associative. We're exploiting the associative property of addition in the two sum problem to achieve the constant time improvement. But that's all he told me. I don't get it to be honest. I still think my code should work. Can someone tell me why my code doesn't work?
Your algorithm (once the if/for mixup is fixed) still doesn't work because subtraction is not commutative. The algorithm only effectively checks x,y pairs where x comes later in the array than y. That's OK when it's testing x+y = target, since it doesn't matter which order the two values are in. But for x-y = target, the order does matter, since x - y is not the same thing as y - x.
A fix for this would be to check each number in the array to see if it could be either x or y with the other value being one of the earlier values from arr. There needs to be a different check for each, so you probably need two if statements inside the loop:
seen = set()
for n in arr:
if n-target in seen:
x = n
y = n-target
return [x,y]
if n+target in seen:
x = n+target
y = n
return [x,y]
seen.add(x)
Note that I renamed the loop variable to n, since it could be either x or y depending on how the math worked out. It's not strictly necessary to use x and y variables in the bodies of the if statements, you could do those computations directly in the return statement. I also dropped the unneeded enumerate call, since the single-loop versions of the code don't use i at all.

Python: Coordinate Conversion

I have a slice of a set of lists of coordinates a[:,4]. It is in astronomical coordinates, which I'd like to convert to decimal. However, it currently doesn't work for negative astronomical coordinates. I currently have:
if any(a[:,4] < 0 ):
b[:,1] = a[:,4] - a[:,5]/60 - a[:,6]/3600 - a[:,7]/360000
else:
b[:,1] = a[:,4] + a[:,5]/60 + a[:,6]/3600 + a[:,7]/360000
print b
The aim of this is to get it to identify if the coordinate is negative or not from the a[:,4] coordinate and then process the other coordinates one way if it is negative, and the other way if it is positive. However, the "if any" line doesn't appear to be working.
For example, -09:24:40.25 should convert to -9.41118, but it currently converts to -8.58882, as the negative "hours" coordinate is then having the arcminute, arcsecond and milliarcsecond coordinates added to it, instead of them being subtracted.
I'm not sure what I'm doing wrong.
Thanks!
You can't use the any function like that assuming you're using a python list, as it takes an iterable and returns true if ANY of that iterable is true
a < 0
won't return an iterable
replace it with
[i < 0 for i in a[:,4]]
or
map(lambda x: x < 0 ,a[:,4])
so that the if statement becomes
if any(map(lambda x: x < 0,a[:,4])):
or
if any([i < 0 for i in a[:,4]])

Categories