Path: news.mathworks.com!not-for-mail
From: "William Dampier" <walldo2@gmail.com>
Newsgroups: comp.soft-sys.matlab
Subject: Re: finding consecutive numbers (runs)
Date: Wed, 12 Dec 2007 21:59:30 +0000 (UTC)
Organization: Drexel University
Lines: 98
Message-ID: <fjplk2$fgm$1@fred.mathworks.com>
References: <fjp9pj$p8g$1@fred.mathworks.com> <fjpihi$p2j$1@fred.mathworks.com>
Reply-To: "William Dampier" <walldo2@gmail.com>
NNTP-Posting-Host: webapp-02-blr.mathworks.com
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 8bit
X-Trace: fred.mathworks.com 1197496770 15894 172.30.248.37 (12 Dec 2007 21:59:30 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Wed, 12 Dec 2007 21:59:30 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 1084889
Xref: news.mathworks.com comp.soft-sys.matlab:442232


"Roger Stafford" <ellieandrogerxyzzy@mindspring.com.invalid>
wrote in message <fjpihi$p2j$1@fred.mathworks.com>...
> "William Dampier" <walldo2@gmail.com> wrote in message
<fjp9pj$p8g
> $1@fred.mathworks.com>...
> > I am trying to find a speedy way to find the number of
> > consecutive 1's in a vector of logicals in with the
> > following type of output.
> > 
> > input =    [1 0 1 1 1 0 1 1 0 0 0 1 0 1]
> > desired1 = [1 0 3 2 1 0 2 1 0 0 0 1 0 1]
> > desired2 = [1 0 1 2 3 0 1 2 0 0 0 1 0 1] %the reverse
direction
> > 
> > desired1=zeros(size(input));
> > spots=find(input);
> >     desired1(1:spots(1))=(spots(1)-1):-1:0;
> >     for k=2:length(spots)-1
> >        
> > desired1(spots(k-1):spots(k))=(spots(k)-spots(k-1)):-1:0;
> >     end
> > 
> > 
> > I understand to avoid for-loops but I didn't see a way
> > around it in this case.  The real input is actually a matrix
> > of logicals in which I want the to do apply this to each row
> > individually (so if you see a vectorized solution I would
> > certainly be appreciative).  Currently I find desired2 using
> > the same algorithm on fliplr(input).
> > 
> > real_input =   [1 0 1 1 1 0 0 1 0 0 1 1 0;
> >                 0 1 0 0 1 1 1 0 1 1 0 0 0];
> > real_desired = [1 0 3 2 1 0 0 1 0 0 2 1 0;
> >                 0 1 0 0 3 2 1 0 2 1 0 0 0];
> > 
> > The real data is also a ~6000 X 9000 matrix so I'd like to
> > avoid creating too many temporary arrays.
> -----------------
>   If x is an m by n matrix of your inputs, then the
following y matrix below 
> should be the 'desired2' matrix you requested.  The
'desired1' matrix can be 
> obtained by repeating the same process using fliplr(x) in
place of x (the 
> reverse direction of what you mentioned.)  I was too lazy
to try for a 
> simultaneous solution of both matrices.
> 
>  [m,n] = size(x);
>  y = [zeros(1,m);x.'];
>  y = y(:);
>  p = find(~y);
>  y(p) = [0;1-diff(p)];
>  y = reshape(cumsum(y),[],m).';
>  y(:,1) = [];
> 
> Roger Stafford
> 

Thanks a whole lot.

It took me a few minutes to realize that if I fliplr(input)
then I'll also have to fliplr the output as well. like this:

input=[1 0 1 1 1 0 1 1 0 0 0 1 0 1];


x=input;
[m,n] = size(x);
y = [zeros(1,m);x.'];
y = y(:);
p = find(~y);
y(p) = [0;1-diff(p)];
y = reshape(cumsum(y),[],m).';
y(:,1) = [];

x=fliplr(input);
[m,n] = size(x);
y2 = [zeros(1,m);x.'];
y2 = y2(:);
p = find(~y2);
y2(p) = [0;1-diff(p)];
y2 = reshape(cumsum(y2),[],m).';
y2(:,1) = [];

desired=[input; y; fliplr(y2)]

This shaves more than 40 seconds off of each of ~3000
iterations (dividing training/testing dataset) so the final
speed up is very large!

Thanks again