I have a vector V periodic an I want to write a program which associates to each period the set of different elements in that period and gives its cardinal.
For example:
For the vector v=(2 3 7 2 7 3 2 3 7 2 7 3) and cardinal 6, give me only the vector P=(2 3 7 2 7 3).
For The vector v=(2 3 7 5 8 6 10 11 10 6 8 5 7 3 2 3 7 5 8 6) and the cardinal 14, give me P=(2 3 7 5 8 6 10 11 10 6 8 5 7 3).
If I understood you correctly you have to use build-in function seqperiod(v).
In your case, for example:
v=[2 3 7 5 8 6 10 11 10 6 8 5 7 3 2 3 7 5 8 6];
>> seqperiod(v)
ans =
14
Interesting moment: in your second example there aren't full repetition. So we can't really say is it periodic... But seqperiod still works and returns 14 as you wish.
go further you can use it in this way:
[p, num] = seqperiod(v);
p = 14
num = 1.4286
num - is a number of repetitions.
Ok. Now you say you need not only the cardinal, but the vector. So you can do it easily:
result = v(1:p);
Hope it helps!
Related
Given two parameters:
n %number of repetitions per value
k %max value to repeat
I would like to create a vector of size n*k, which is a concatenation of k vectors of size n, such that the i'th vector contains the value i at each coordinate.
Example:
n = 5;
k = 9;
Desired result:
[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9,9,9];
Is there an elegant way to achieve this?
Thanks!
quite a few ways to do it:
method 1:
A=1:k
repelem(A',n,1)'
method 2:
A=1:k
kron(A', ones(n,1))'
method 3:
A=1:k
B=repmat(A, n, 1)
B(:)'
method 4:
A=1:k
B=ones(n,1)*A
B(:)'
Here is an alternative method
A = reshape(mtimes((1:k).',ones(1,n)).',1,n*k)
A =
Columns 1 through 22
1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 5 5
Columns 23 through 44
5 5 5 6 6 6 6 6 7 7 7 7 7 8 8 8 8 8 9 9 9 9
Column 45
9
It multiplies each element by ones n times
>> mtimes((1:k).',ones(1,5)).'
ans =
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
and then reshapes the whole matrix to one vector
I currently have a 3 by 3 matrix "m":
1 2 3
4 5 6
7 8 9
I would like to add a row to matrix 'm' to have a resultant matrix of:
1 2 3
4 5 6
7 8 9
10 11 12
A matrix in q is just a list of lists where inner lists represent rows.
m: ((1 2 3);(4 5 6);(7 8 9))
In order to add one more row all you have to do is add one more inner list to it:
m: m,enlist 10 11 12
enlist is important here, without it you'll end up with this:
q)((1 2 3);(4 5 6);(7 8 9)),10 11 12
1 2 3
4 5 6
7 8 9
10
11
12
I agree; using 0N!x to view the structure is very useful.
To achieve what you want then you can simply do;
q)show m:3 cut 1+til 9 /create matrix
1 2 3
4 5 6
7 8 9
q)show m,:10 11 12 /join new 'row'
1 2 3
4 5 6
7 8 9
10 11 12
q)
I have a 3D matrix and I want to store each 2D component of this in the row of another 2D matrix which has many rows as the 3rd dimension of the 3D matrix.
How can I do this?
With permute & reshape -
reshape(permute(A,[3 2 1]),size(A,3),[])
Sample run -
>> A
A(:,:,1) =
7 1 7 5
3 4 8 5
9 4 2 6
A(:,:,2) =
7 7 2 4
7 6 5 6
3 2 9 3
A(:,:,3) =
7 7 5 3
3 9 2 8
5 9 2 3
>> reshape(permute(A,[3 2 1]),size(A,3),[])
ans =
7 1 7 5 3 4 8 5 9 4 2 6
7 7 2 4 7 6 5 6 3 2 9 3
7 7 5 3 3 9 2 8 5 9 2 3
If you don't mind a little indexing madness...
You can build a linear index with the appropriate shape, which applied on the original array will give the desired result:
B = A(bsxfun(#plus, (1:L*M:L*M*N).', reshape(bsxfun(#plus, (0:L:L*M-1).', 0:L-1),1,[])));
Example:
>> A = randi(10,2,3,4)-1; %// example array; size 2x3x4
>> A
A(:,:,1) =
5 3 2
9 8 9
A(:,:,2) =
8 7 4
9 8 6
A(:,:,3) =
3 4 8
0 4 4
A(:,:,4) =
2 8 8
4 6 7
Result:
>> B
B =
5 3 2 9 8 9
8 7 4 9 8 6
3 4 8 0 4 4
2 8 8 4 6 7
That is easily done with MATLABs matrix unrolling syntax:
A=ones(N,M,O);
B=zeros(O,N*M);
for ii=1:size(A,3)
aux=A(:,:,ii); % aux is NxM
B(ii,:)=aux(:); % unroll!
end
(note I called O the thing you call N in your pictures)
Anybody know a fast way to produce a matrix consisting of a linspace for each row? For example, the sort of pattern I'm looking for in this matrix is:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
...
1 2 3 4 5 6 7 8 9 10
Anyone know any fast tricks to produce this WITHOUT using a for loop?
I just figured this out, so just in case anyone else was troubled by this, we can achieve this exact pattern by:
a=linspace(1,10,10);
b=ones(3,1)*a;
This will give:
>> a = 1 2 3 4 5 6 7 8 9 10
>> b = 1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
You need to use repmat.
Example:
>> B = repmat(1:10,[3 1])
B =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
You can vary the value of 3 there. You can change it accordingly.
Another shortcut I can recommend is similar to repmat, but you specify a base array first of a = 1:10;. Once you do this, you specify a series of 1s in the first dimension when indexing which should produce a matrix of the same vectors with many rows as you want, where each row consists of the base array a. As such:
%// number of times to replicate
n = 4;
a = 1:10;
a = a(ones(1,n),:);
Result:
a =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
Insert this command: transpose(ndgrid(1:10,1:n));, where n is the number of rows desired in the result.
You can consider these solutions:
With basic matrix indexing (taken from here)
b=a([1:size(a,1)]' * ones(1,NumToReplicate), :) %row-wise replication
b=a(:, ones(NumToReplicate, 1)) %column-wise replication
With bsxfun:
bsxfun(#times,a,(ones(1,NumToReplicate))') %row-wise replication
bsxfun(#times,a',(ones(1,NumToReplicate))) %column-wise replication
You are welcome to benchmark above two solutions with repmat.
so far I have this:
for l=1:50
%# matrix of distances between terminal nodes, index of column represents
%# where the searcher is going from and the index of the row represents
%# where the searcher is going to
d = [
10 2 2 3 3 2 4 5 5 4 4 4 3 3 4 4;
10 10 2 5 5 4 6 7 7 6 6 6 5 5 6 6;
10 2 10 5 5 4 6 7 7 6 6 6 5 5 6 6;
10 5 5 10 2 3 7 8 8 7 7 7 6 6 7 7;
10 5 5 2 10 3 7 8 8 7 7 7 6 6 7 7;
10 4 4 3 3 10 6 7 7 6 6 6 5 5 6 6;
10 6 6 7 7 6 10 3 3 2 4 4 5 5 6 6;
10 7 7 8 8 7 3 10 2 3 5 5 6 6 7 7;
10 7 7 8 8 7 3 2 10 3 5 5 6 6 7 7;
10 6 6 7 7 6 2 3 3 10 4 4 5 5 6 6;
10 6 6 7 7 6 4 5 5 4 10 2 5 5 6 6;
10 6 6 7 7 6 4 5 5 4 2 10 5 5 6 6;
10 5 5 6 6 5 5 6 6 5 5 5 10 2 3 3;
10 5 5 6 6 5 5 6 6 5 5 5 2 10 3 3;
10 6 6 7 7 6 6 7 7 6 6 6 3 3 10 2;
10 6 6 7 7 6 6 7 7 6 6 6 3 3 2 10
];
i=1; %# start the searcher at the origin
h=5;
t=0; %# start time of the game
k=find(d(i,:)==min(d(i,:))); %# position closest nodes
j=randsample(k,1,true); %# randomly selects closest node if multiple nodes within closest distance
c=min(d(i,:));
while j~=h %# while the searcher is not in the same position as the hider
d(:,j)=[]; %# delete the column corresponding to the searchers position so he cannot return here
%# want to ignore all previous positions not delete them!
i=j; %# reset the searchers current position
k=find(d(i,:)==min(d(i,:))) %# find the new minimum distance
p=rand(1)*length(k); %# randomly select an index of k
q=floor(p)+1 %# take the integer part of k
j=k(q) %# randomly select from all the closest nodes
t=t+min(d(i,:))+c; %# calculate cumulative time for paths traveled
end
Found(l)=j-1 %# show position where the hider was found (relate matrix index to node index)
Time(l)=t %# show time taken for the searcher to find the hider
end
So the elements in d are the distance between two positions, represented by the row and column position, then the aim is to reach column 5 (h) by traveling the shortest distances between positions.
The problem I have is that I am currently deleting each column as it is searched for the minimum distance, this is then redefining the index of the column and so when h is either not being reached or it is not the correct h. How can I ignore rows already searched in the 'while' loop?
Any help will be gratefully received, thank you.
You can create an array flags=zeros(16,1) and turn flag(i)=1 when you visit the row. Then you can check whether a row was flagged.