Find first 1 of the first sting of 1s who's length exceed the length of every subsequent string of 0s
Afficher commentaires plus anciens
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
Réponse acceptée
Plus de réponses (4)
Walter Roberson
le 7 Avr 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 commentaires
Alexandre
le 8 Avr 2011
Walter Roberson
le 8 Avr 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
le 8 Avr 2011
tril(true(size(T)))
Walter Roberson
le 8 Avr 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
le 13 Avr 2011
Andrei Bobrov
le 14 Avr 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 commentaires
Matt Fig
le 14 Avr 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
le 14 Avr 2011
Thank you Matt, for your note ... adjusted ...
Matt Fig
le 14 Avr 2011
Your welcome.
But now it returns multiple values:
V = [0 1 1 1 1 1 0 1 1 1]
Andrei Bobrov
le 14 Avr 2011
Thanks, Matt ... I feel like Ovechkin in Vancouver in 2010 in the finals ... once corrected, sorry for the careless ...
Matt Fig
le 14 Avr 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
le 14 Avr 2011
I think empty matrix
Matt Fig
le 14 Avr 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
le 14 Avr 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 commentaires
Matt Fig
le 14 Avr 2011
It looks like the file by Us returns what I have for:
[x; [n length(v)-sum(n)]]
Oleg Komarov
le 16 Avr 2011
Rude is just a run-length encoder/decoder. Basically I use it in order to avoid rewriting the algorithm all the time :)
Alexandre
le 23 Avr 2011
0 votes
Catégories
En savoir plus sur Loops and Conditional Statements dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!