Find first 1 of the first sting of 1s who's length exceed the length of every subsequent string of 0s
Show older comments
Hi, I'm building a function to analyse american options and in the method I use I need to find or create an efficient algorithm that will analyse a vector made of ones and zeros and find the position of the first 1 of the first string of 1 which length exceeds the length of every subsequent string of 0. Example if the vector is v=[1,0,0,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,*1,1,1,0,0,1,1,1,1,0,0,1,0,1,1,1,1,1,1], the algorithm analysing the vector v should return the position of the *1...which is 19.
Anyone has any idea or knows commands that could help me?
Thank you Alex
Accepted Answer
More Answers (4)
Walter Roberson
on 7 Apr 2011
Fractional answer that you might be able to flesh out:
>> reshape([find(~v,1)-1 diff(find(diff(v)))],2,[])
ans =
1 4 2 3 4 1
2 3 6 2 2 1
The upper row is the length of runs of 1's, the lower row is the length of runs of 0's that follow immediately thereafter.
Adjustments would have to be made for the case the array starts with 0 or ends in 0.
I can think of a way to test for the location you want using arrayfun() to do a hidden for loop, but perhaps when I've had some sleep I will think of a better way.
5 Comments
Alexandre
on 8 Apr 2011
Walter Roberson
on 8 Apr 2011
For that sub-case
T = reshape([find(~v,1)-1 diff(find(diff(v)))],2,[]);
L = find(all( bsxfun(@gt,(1:size(T,2)).',1:size(T,2)) | bsxfun(@gt,T(1,:).', T(2,:)), 2),1);
P = 1 + sum(reshape(T(:,1:L-1),1,[]));
As mentioned above this would need to be tweaked for cases beginning or ending with 0.
The first bsxfun creates a lower-diagonal logical matrix. There might well be a better way (or at least a more readable way) to do that.
Sean de Wolski
on 8 Apr 2011
tril(true(size(T)))
Walter Roberson
on 8 Apr 2011
tril shouds like a good idea. It would have to be adjusted in this instance to
tril(true(size(T,2)),-1)
in order to exclude the diagonal.
Alexandre
on 13 Apr 2011
Andrei Bobrov
on 14 Apr 2011
use ideas of Walter Roberson and Matt Fig
v = v(:)';
ne = diff(find(diff([~v(1) v(:)' ~v(end)]))); % Walter Roberson
I = 1:length(v);
Ifirst = I([true diff(v)~=0]); % Matt Fig
tarr = v(Ifirst);
seq = find(tarr==1,1,'first'):find(tarr==0,1,'last');
ii = 1:2:length(seq);
logtlz = diff(ne(seq)) < 0;
Iof = Ifirst(seq(ii));
Iout = Iof(logtlz(ii));
My long variant
vt = [~v(1);v(:);~v(end)];
o = find(vt);
z = find(~vt);
nz = diff(o);
no = diff(z);
nz = nz(nz~=1)-1;
no = no(no~=1)-1;
t = length(no)-length(nz);
x = diff([[no;zeros(t<0)],[nz;zeros(t>0)]],[],2);
v1c = mat2cell(find(v(:)'),1,no);
Iout = cellfun(@(x)x(1),v1c(find((x(1:end-(t~=0|v(end)>0))<0))))
7 Comments
Matt Fig
on 14 Apr 2011
Both of these solutions fail for certain cases. For example:
v = [0 1 0 0 0 1 1 1 1 0];
The first solution returns 3 (should be 6) and the second errors.
Andrei Bobrov
on 14 Apr 2011
Thank you Matt, for your note ... adjusted ...
Matt Fig
on 14 Apr 2011
Your welcome.
But now it returns multiple values:
V = [0 1 1 1 1 1 0 1 1 1]
Andrei Bobrov
on 14 Apr 2011
Thanks, Matt ... I feel like Ovechkin in Vancouver in 2010 in the finals ... once corrected, sorry for the careless ...
Matt Fig
on 14 Apr 2011
Getting closer!
V = [1 1 0 1 0 0 0 1 0 1]
I think your solution could be made to work! By the way, I am just doing this over and over:
V = round(rand(1,10))
find_run_ones(V) % MATT FIG
find_run_ones2(V) % ABOBROFF
About the only thing that is a little ambiguous to me is whether or not to say that a string ending in 1s counts for Alexandre. For example:
V = [0 1 1 1]
Do we return 2 or an empty matrix?? Oleg thinks an empty array is appropriate, whereas my current solution takes the latter approach.
Andrei Bobrov
on 14 Apr 2011
I think empty matrix
Matt Fig
on 14 Apr 2011
If so, then simply replacing this line in my code:
I = Lx; % The return variable.
with this:
I = 0; % The return variable.
will work force an [] to return.
Oleg Komarov
on 14 Apr 2011
EDIT to take into account empty out for v = [0 1 1 1]
[len,val] = rude(v);
out = [];
for b = find(val)
if len(b) > len(b+1:2:end)
out = sum(len(1:b-1))+1
return
end
end
2 Comments
Matt Fig
on 14 Apr 2011
It looks like the file by Us returns what I have for:
[x; [n length(v)-sum(n)]]
Oleg Komarov
on 16 Apr 2011
Rude is just a run-length encoder/decoder. Basically I use it in order to avoid rewriting the algorithm all the time :)
Alexandre
on 23 Apr 2011
0 votes
Categories
Find more on Characters and Strings in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!