Question

I need an algorithm in Matlab which counts how many adjacent and non-overlapping (1,1) I have in each row of a matrix A mx(n*2) without using loops. E.g.

A=[1 1 1 0 1 1 0 0 0 1; 1 0 1 1 1 1 0 0 1 1]  %m=2, n=5

Then I want

B=[2;3] %mx1
Was it helpful?

Solution

Specific case

Assuming A to have ones and zeros only, this could be one way -

B = sum(reshape(sum(reshape(A',2,[]))==2,size(A,2)/2,[]))

General case

If you are looking for a general approach that must work for all integers and a case where you can specify the pattern of numbers, you may use this -

patt = [0 1] %%// pattern to be found out
B = sum(reshape(ismember(reshape(A',2,[])',patt,'rows'),[],2))

Output

With patt = [1 1], B = [2 3]

With patt = [0 1], B = [1 0]

OTHER TIPS

you can use transpose then reshape so each consecutive values will now be in a row, then compare the top and bottom row (boolean compare or compare the sum of each row to 2), then sum the result of the comparison and reshape the result to your liking.

in code, it would look like:

A=[1 1 1 0 1 1 0 0 0 1; 1 0 1 1 1 1 0 0 1 1] ;
m = size(A,1) ;
n = size(A,2)/2 ;

Atemp = reshape(A.' , 2 , [] , m ) ;
B = squeeze(sum(sum(Atemp)==2))


You could pack everything in one line of code if you want, but several lines is usually easier for comprehension. For clarity, the Atemp matrix looks like that:

Atemp(:,:,1) =
     1     1     1     0     0
     1     0     1     0     1
Atemp(:,:,2) =
     1     1     1     0     1
     0     1     1     0     1

You'll notice that each row of the original A matrix has been broken down in 2 rows element-wise. The second line will simply compare the sum of each row with 2, then sum the valid result of the comparisons. The squeeze command is only to remove the singleton dimensions not necessary anymore.

you can use imresize , for example

  imresize(A,[size(A,1),size(A,2)/2])>0.8

ans =
 1     0     1     0     0
 0     1     1     0     1

this places 1 where you have [1 1] pairs... then you can just use sum

For any pair type [x y] you can :

x=0; y=1;
R(size(A,1),size(A,2)/2)=0; % prealocarting memory

 for n=1:size(A,1)
    b=[A(n,1:2:end)'  A(n,2:2:end)']
    try
       R(n,find(b(:,1)==x & b(:,2)==y))=1;
    end

end

R =
 0     0     0     0     1
 0     0     0     0     0

With diff (to detect start and end of each run of ones) and accumarray (to group runs of the same row; each run contributes half its length rounded down):

B = diff([zeros(1,size(A,1)); A.'; zeros(1,size(A,1))]); %'// columnwise is easier
[is js] = find(B==1); %// rows and columns of starts of runs of ones
[ie je] = find(B==-1); %// rows and columns of ends of runs of ones
result = accumarray(js, floor((ie-is)/2)); %// sum values for each row of A
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top