Imagine I am given a matrix, I need to count how many near crosses there are. A near cross is an extension of a normal cross, which means the same number across an entire row and an entire column of the matrix but the number at the intersection could be different. How should I approach finding crosses and then testing for near crosses?
Test Cases:
[[1, 1, 1, 1, 1],
[2, 2, 1, 3, 3],
[1, 2, 1, 2, 2],
[5, 5, 1, 6, 6],
[2, 2, 1, 1, 1]]
and
[[1, 1, 0, 1, 1],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0]]
both have 1 near cross in them.
[[1, 1, 0, 1, 1],
[0, 0, 1, 1, 0],
[1, 1, 1, 0, 1],
[0, 0, 1, 1, 0],
[0, 0, 1, 1, 0]]
has 2 near crosses.
CodePudding user response:
You could use Counter
to identify which rows have at most one deviating value. This is true when one frequency is at least n-1
, where n
is the number of columns.
Then you could list the deviation point (coordinates), or all points on the row (when there is no deviating value). This gives a set of coordinates that each could be the crossing point of a near-cross.
Transpose the matrix and repeat the above filtering, and then mirror each of the resulting points (x vs. y)
As a result you'll have two sets of potential crossing points. The intersection of these two sets will give the actual crossing points of near-crosses.
Here is an implementation of that algorithm:
from collections import Counter
def transpose(matrix):
return [list(row) for row in zip(*matrix)]
def potentialcrosspoints(matrix):
n = len(matrix[0])
for i, row in enumerate(matrix):
entries = list(Counter(row).items())
if len(entries) == 1:
for j in range(n):
yield i, j
elif n - 1 in (entries[0][1], entries[1][1]):
yield i, row.index(entries[int(entries[1][1] == 1)][0])
def mirrorpoints(points):
return [(j, i) for i, j in points]
def countnearcrosses(matrix):
return len(set(potentialcrosspoints(matrix)).intersection(
mirrorpoints(potentialcrosspoints(transpose(matrix)))))
# Run of the last example in the question
matrix = [[1, 1, 0, 1, 1],
[0, 0, 1, 1, 0],
[1, 1, 1, 0, 1],
[0, 0, 1, 1, 0],
[0, 0, 1, 1, 0]]
total = countnearcrosses(matrix)
print(total) # 2