Reputation: 27
I have a NxM matrix encoded in 0s and 1s - where only the 1s are to be printed in its respective locations whereas the 0s are blank spaces, such as the following matrix:
m = [[0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0]
[1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1]
My question is how can I create a starting point from the change that takes place from a 0 to a 1 and an end point from the change that takes place from a 1 to a 0 in each row. Then print all the 1s between the start point and end point
I have the following code (which does not work):
nrows, ncols = m.shape #gets the shape of the matrix
for r in range(nrows):
for c in range(ncols):
if m[r,c] == 0 and m[r,c+1] == 1: #checks if there is a 0 first and then a 1 in the next index of the column in the row to create a starting point
start = m[r,c+1]
if m[r,c] == 1 and m[r,c+1] == 0: #checks if there is a 1 first and then a 0 in the next index of the column in the row to create an end point
end = m[r, c+1]
My desired output is, for example taking the lastrow into consideration:
It should print everything between the first 1 and last 1 before a 0 is found in that row, excluding the 0s. So basically this: 1 1 1 1....1 1 1 1 1 1....1 1 The dots (.)represent the 0s that have to be excluded All help and advice will be highly appreciated.
Upvotes: 1
Views: 293
Reputation: 41872
Is your goal the printed output or is your goal the markers that indicate where 1's begin and end? If your goal is just the printed output, why not something simple like:
m = [[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]
]
for row in m:
for bit in row:
print(bit or ' ', end=' ')
print()
OUTPUT
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
Manipulate as you see fit to eliminate the spaces for the zeros or spaces between the 1's (i.e. ' '
space vs. ''
empty string.)
Do you mind showing/explaining on how I am able to get the markers where the 1s begin and end?
Borrowing from an SO answer to Identify groups of continuous numbers in a list, we can do:
for row in m:
indicies = compress(count(), row)
ranges = []
for _, g in groupby(enumerate(indicies), lambda x: x[0] - x[1]):
group = [x[1] for x in g]
ranges.append((group[0], group[-1]))
print(ranges)
OUTPUT
[(7, 10)]
[(7, 10)]
[(5, 8)]
[(5, 8)]
[(14, 17)]
[(14, 17)]
[(0, 3), (8, 13), (18, 19)]
Upvotes: 1
Reputation: 9010
Here's a straight forward way of getting the successive differences into a new array.
coded = np.append(m[:,:1]*2-1, m[:,1:] - m[:,:-1], axis=1)
# [[-1 0 0 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 0 0 0]
# [-1 0 0 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 0 0 0]
# [-1 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0]
# [-1 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0]
# [-1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -1 0]
# [-1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -1 0]
# [ 1 0 0 0 -1 0 0 0 1 0 0 0 0 0 -1 0 0 0 1 0]]
In this array, a -1 indicates the start of a spree of 0's, and a 1 indicates the start of a spree of 1's. I'm not exactly clear on what you're trying to do, but maybe this will help.
Upvotes: 0
Reputation: 77857
You haven't given a viable MCVE yet; I converted this to Python and made a solution.
You take each row, shift it left one position, and subtract from the original. This will mark all transitions with 1 and -1. Then you just need to find the first 0=>1 change, and then the 1=>0 change after that. Adjust the indices as you see fit.
Note: I kept this low-tech. The solution can be greatly shortened if you convert the lists to bitmaps, find transitions with XOR, and be careful about marking the starting value (if it starts with 1, then you need the 2nd & 3rd transitions, not the first two).
m = [[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]
]
for row in range(len(m)):
line = m[row]
first = line[:-1]
shift = line[1:]
diff = [first[i] - shift[i] for i in range(len(first))]
l_bound = diff.index(-1) + 1
r_bound = diff[l_bound:].index(1) + l_bound
print
print row, '\t', line
print '\t', diff
print '\t', l_bound, r_bound
Output:
0 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
7 10
1 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
7 10
2 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
5 8
3 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
5 8
4 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0]
14 17
5 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0]
14 17
6 [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]
[0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0]
8 13
Upvotes: 0