Find the longest run of sequential integers in a vector - matlab

I have a routine that returns a list of integers as a vector.
Those integers come from groups of sequential numbers; for example, it may look like this:
vector = 6 7 8 12 13 14 15 26 27 28 29 30 55 56
Note that above, there are four 'runs' of numbers (6-8, 12-15, 26-30 & 55-56). What I'd like to do is forward the longest 'run' of numbers to a new vector. In this case, that would be the 26-30 run, so I'd like to produce:
newVector = 26 27 28 29 30
This calculation has to be performed many, many times on various vectors, so the more efficiently I can do this the better! Any wisdom would be gratefully received.

You can try this:
v = [ 6 7 8 12 13 14 15 26 27 28 29 30 55 56];
x = [0 cumsum(diff(v)~=1)];
v(x==mode(x))
This results in
ans =
26 27 28 29 30

Here is a solution to get the ball rolling . . .
vector = [6 7 8 12 13 14 15 26 27 28 29 30 55 56]
d = [diff(vector) 0]
maxSequence = 0;
maxSequenceIdx = 0;
lastIdx = 1;
while lastIdx~=find(d~=1, 1, 'last')
idx = find(d~=1, 1);
if idx-lastIdx > maxSequence
maxSequence = idx-lastIdx;
maxSequenceIdx = lastIdx;
end
d(idx) = 1;
lastIdx=idx;
end
output = vector(1+maxSequenceIdx:maxSequenceIdx+maxSequence)
In this example, the diff command is used to find consecutive numbers. When numbers are consecutive, the difference is 1. A while loop is then used to find the longest group of ones, and the index of this consecutive group is stored. However, I'm confident that this could be optimised further.

Without loops using diff:
vector = [6 7 8 12 13 14 15 26 27 28 29 30 55 56];
seqGroups = [1 find([1 diff(vector)]~=1) numel(vector)+1]; % beginning of group
[~, groupIdx] = max( diff(seqGroups)); % bigger group index
output = vector( seqGroups(groupIdx):seqGroups(groupIdx+1)-1)
output vector is
ans =
26 27 28 29 30

Without loops - should be faster
temp = find ( ([(vector(2:end) - vector(1:end-1))==1 0])==0);
[len,ind]=max(temp(2:end)-temp(1:end-1));
vec_out = vector(temp(ind)+1:temp(ind)+len)

Related

how I delete combination rows that have the same numbers from matrix and only keeping one of the combinations?

for a=1:50; %numbers 1 through 50
for b=1:50;
c=sqrt(a^2+b^2);
if c<=50&c(rem(c,1)==0);%if display only if c<=50 and c=c/1 has remainder of 0
pyth=[a,b,c];%pythagorean matrix
disp(pyth)
else c(rem(c,1)~=0);%if remainder doesn't equal to 0, omit output
end
end
end
answer=
3 4 5
4 3 5
5 12 13
6 8 10
7 24 25
8 6 10
8 15 17
9 12 15
9 40 41
10 24 26
12 5 13
12 9 15
12 16 20
12 35 37
14 48 50
15 8 17
15 20 25
15 36 39
16 12 20
16 30 34
18 24 30
20 15 25
20 21 29
21 20 29
21 28 35
24 7 25
24 10 26
24 18 30
24 32 40
27 36 45
28 21 35
30 16 34
30 40 50
32 24 40
35 12 37
36 15 39
36 27 45
40 9 41
40 30 50
48 14 50
This problem involves the Pythagorean theorem but we cannot use the built in function so I had to write one myself. The problem is for example columns 1 & 2 from the first two rows have the same numbers. How do I code it so it only deletes one of the rows if the columns 1 and 2 have the same number combination? I've tried unique function but it doesn't really delete the combinations. I have read about deleting duplicates from previous posts but those have confused me even more. Any help on how to go about this problem will help me immensely!
Thank you
welcome to StackOverflow.
The problem in your code seems to be, that pyth only contains 3 values, [a, b, c]. The unique() funcion used in the next line has no effect in that case, because only one row is contained in pyth. another issue is, that the values idx and out are calculated in each loop cycle. This should be placed after the loops. An example code could look like this:
pyth = zeros(0,3);
for a=1:50
for b=1:50
c = sqrt(a^2 + b^2);
if c<=50 && rem(c,1)==0
abc_sorted = sort([a,b,c]);
pyth = [pyth; abc_sorted];
end
end
end
% do final sorting outside of the loop
[~,idx] = unique(pyth, 'rows', 'stable');
out = pyth(idx,:);
disp(out)
a few other tips for writing MATLAB code:
You do not need to end for or if/else stements with a semicolon
else statements cover any other case not included before, so they do not need a condition.
Some performance reommendations:
Due to the symmetry of a and b (a^2 + b^2 = b^2 + a^2) the b loop could be constrained to for b=1:a, which would roughly save you half of the loop cycles.
if you use && for contencation of scalar values, the second part is not evaluated, if the first part already fails (source).
Regards,
Chris
You can also linearize your algorithm (but we're still using bruteforce):
[X,Y] = meshgrid(1:50,1:50); %generate all the combination
C = (X(:).^2+Y(:).^2).^0.5; %sums of two square for every combination
ind = find(rem(C,1)==0 & C<=50); %get the index
res = unique([sort([X(ind),Y(ind)],2),C(ind)],'rows'); %check for uniqueness
Now you could really optimized your algorithm using math, you should read this question. It will be useful if n>>50.

How to sample matrix elements in matlab

I have a list of coordinates I would like to sample from a Matrix.
Is there any elegant way to do it?
Ideally, something that looks like:
A = magic(5)
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
r = 1:5; % row coordinates
c = 5:-1:1; % column coordinates
A(r,c)
ans =
15 14 13 12 11
Which is equivalent to
for k=1:length(r)
A(r(k), c(k))
end
I am sure someone has asked that, but I couldn't find it anywhere.
Applying #excaza comment I was able to solve this with:
rc_ids = sub2ind(size(A), r,c);
A(rc_ids)

How to select different row in a matrix in Matlab every time?

I want to create a matrix which has distinct rows selected from another matrix.
For Example, I have a 10x3 matrix A
A =
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
16 17 18
19 20 21
22 23 24
25 26 27
28 29 30
Now I want to create a new matrix B of size 2 X 3 from A in a iterative process in such a way that the matrix B should consist different rows in each iteration (max iteration = 5)
My Pseudo-code:
for j=1:5
create matrix 'B' by selecting 2 rows randomly from 'A', which should be different
end
You could use randperm to mess up the rows randomly and then take two rows in each iteration successively in order.
iterations = 4;
permu = randperm(size(A,1));
out = A(permu(1:iterations*2),:);
for ii = 1:iterations
B = out(2*ii - 1:2*ii,:)
end
Results:
B =
22 23 24
25 26 27
B =
1 2 3
13 14 15
B =
19 20 21
16 17 18
B =
7 8 9
10 11 12

How to find out the coefficient in matching pursuit algorithm [duplicate]

This question already has answers here:
Implementing matching pursuit algorithm
(3 answers)
Closed 6 years ago.
I'm trying to implement Matching Pursuit algorithm in Matlab.I have found out the maximum inner product value ,i m stuck with how to find out the coeffients.
help me out.
Here is the algorithm
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
b=[16;17;18;19;20];
n=size(D);
A1=zeros(n);
R=b;
x=[];
H=10;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
[c,d] = max(abs(D'*R));
Here i have used a prefined dictionary.
Thanks in advance
You can use this function based on "S. Mallat, Z. Zhang, 1993. Matching pursuit in a time frequency dictionary. IEEE Transactions Signal Processing, Vol. 41, No. 12, pp. 3397-3415."
x = MP(b,D,10);
function S = MP(y,Dictionary,iteration)
n = size(Dictionary,2);
S = zeros(n,1);
% Normalize the dictionary atoms (coloumns) to have unit norm
% It's better to implement this part out of function,
% to normalize the dictionary just one time!
%**************************************
for j = 1:n;
Dictionary(:,j) = Dictionary(:,j)/norm(Dictionary(:,j));
end
% *************************************
for i = 1:iteration
gn = Dictionary' * y / norm(y);
[MAX,index] = max(abs(gn));
y = y - MAX * Dictionary(:,index);
S(index) = MAX + S(index);
end

Identifying (and removing) sequences from a vector in Matlab/Octave

I'm trying to prune any sequence of length 3 or more from a vector of numbers in Matlab (or Octave). For example, given the vector dataSet,
dataSet = [1 2 3 7 9 11 13 17 18 19 20 22 24 25 26 28 30 31];
removing all sequences of length 3 or more would yield prunedDataSet:
prunedDataSet = [7 9 11 13 22 28 30 31 ];
I can brute force a solution, but I suspect there is a more succinct (and perhaps efficient) way to do it using vector/matrix operations, but I always get confused about whether something yields an index or the value at said index. Suggestions?
Here's the brute force method I came up with:
dataSet = [1 2 3 7 9 11 13 17 18 19 20 22 24 25 26 28 30 31];
benign = [];
for i = 1:size(dataSet,2)-2;
if (dataSet(i) == (dataSet(i+1)-1) && dataSet(i) == dataSet(i+2)-2);
benign = [benign i ] ;
end;
end;
remove = [];
for i = 1:size(benign,2);
remove = [remove benign(i) benign(i)+1 benign(i)+2 ];
end;
remove = unique(remove);
prunedDataSet = setdiff(dataSet, dataSet(remove));
Here's a solution using DIFF and STRFIND
%# define dataset
dataSet = [1 2 3 7 9 11 13 17 18 19 20 22 24 25 26 28 30 31];
%# take the difference. Whatever is part of a sequence will have difference 1
dds = diff(dataSet);
%# sequences of 3 lead to two consecutive ones. Sequences of 4 are like two sequences of 3
seqIdx = findstr(dds,[1 1]);
%# remove start, start+1, start+2
dataSet(bsxfun(#plus,seqIdx,[0;1;2])) = []
dataSet =
7 9 11 13 22 28 30 31
Here's an attempt using vector-matrix notation:
s1 = [(dataSet(1:end-1) == dataSet(2:end)-1), false];
s2 = [(dataSet(1:end-2) == dataSet(3:end)-2), false, false];
s3 = s1 & s2;
s = s3 | [false, s3(1:end-1)] | [false, false, s3(1:end-2)];
dataSet(~s)
The idea is: s1 is true for all positions where a number a appears before a+1. s2 is true for all positions where a appears two positions before a+2. Then s becomes true where both the previous conditions are met. Then, we build s such that every true value is propagated to its two successors.
Finally, dataSet(~s) keeps all the values for which the above conditions are false, that is, it keeps numbers that are not part of a 3-sequence.