Find first 1 of the first sting of 1s who's length exceed the length of every subsequent string of 0s
Mostra commenti meno recenti
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
Risposta accettata
Più risposte (4)
Walter Roberson
il 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 Commenti
Alexandre
il 8 Apr 2011
Walter Roberson
il 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
il 8 Apr 2011
tril(true(size(T)))
Walter Roberson
il 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
il 13 Apr 2011
Andrei Bobrov
il 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 Commenti
Matt Fig
il 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
il 14 Apr 2011
Thank you Matt, for your note ... adjusted ...
Matt Fig
il 14 Apr 2011
Your welcome.
But now it returns multiple values:
V = [0 1 1 1 1 1 0 1 1 1]
Andrei Bobrov
il 14 Apr 2011
Thanks, Matt ... I feel like Ovechkin in Vancouver in 2010 in the finals ... once corrected, sorry for the careless ...
Matt Fig
il 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
il 14 Apr 2011
I think empty matrix
Matt Fig
il 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
il 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 Commenti
Matt Fig
il 14 Apr 2011
It looks like the file by Us returns what I have for:
[x; [n length(v)-sum(n)]]
Oleg Komarov
il 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
il 23 Apr 2011
0 voti
Categorie
Scopri di più su Loops and Conditional Statements in Centro assistenza e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!