Finding right triangle coordinates in binary array

2019-06-09 05:22发布

问题:

Say I have an MxN binary matrix. It is not necessarily sparse. I'm interested in finding the coordinates of the apexes of all of the right triangles in the array. By right triangle, I mean: pretend that the 1 or True values in the matrix are vertices of triangles, and the 0's or False elements are null. Then a right triangle is an arrangement that visually forms a right triangle. By apex I mean the vertex which corresponds to the right angle of the triangle. E.g. in the following 5x6 array:

0 0 1 0 1 0
0 1 0 0 0 0
1 0 0 1 0 1
0 0 1 0 0 0
0 0 0 0 0 0

There is only 1 right triangle. It is the triangle with vertices at: (0,2) is the apex, (3,2) is the lower left, (0,4) is the upper right, where I'm indexing from 0, starting at the top left [Python indexing].


For a given MxN array, I want a Python function F(A) that returns an array L of subarrays, where each subarray is the coordinate pair of the apex of the right triangles in the array. For the case where the same element of the array is the apex of multiple triangles, ultimately I'll just want unique subarrays, but for now the function can duplicate them. As an example, for the array A above, F(A) would return the array L = [[0,2]]


My first thought would be to use row and column sums. Those rows with a row sum >= 2 are worth exploring, and then use the columns sum >=2. Then you would need an efficient way to find the intersections. I would be interested in a function using this method or any other method which might be better and faster.

{E.g. as an alternative, you could think about this from a graph theory perspective. The rows and columns would be nodes of a bipartite graph [the rows would be one set, the columns the other set]. Then the matrix shown here would be one quadrant of the adjacency matrix of the full bipartite graph. In other words, it would be the part of only the cross terms between the row and column sets, since the within set parts would all be 0 since the row nodes don't connect to other row nodes; only to column nodes. From this perspective, a right triangle would look like a path of length 3 on the bipartite graph. I think the matrix approach is simpler, but I'm open to any algorithms here.}

回答1:

Yes, I believe that you're over-thinking this. Generate the row and column sums, and check each array location for intersection.

I haven't tested the syntax, but it will be something like this:

# Generate row and column sums
row_sums = (sum(A[M]) for M in range(len(A)))
col_sums = (sum([A[M, N] for M in range(len(A))] for N in range len(A[0]))

# Now, check each element in the array for being a vertex
vertices = 
    [(row, col) if A[row, col] and row_sums[row] > 1
                               and col_sums[col] > 1
          for row in range(len(A)) for col in range(len(A[0]))]

# You now have a list of all solutions, with no duplicates.