Generate a vector in MATLAB - matlab

I am trying to solve a MATLAB problem to generate a vector like 1,2,2,3,3,3,4,4,4,4...
So if n = 3, then return
[1 2 2 3 3 3]
And if n = 5, then return
[1 2 2 3 3 3 4 4 4 4 5 5 5 5 5]
This is what I came up with:
ans=1
for n=2:n
ans=[ans n*ones(1,n)]
end
But I'm trying to minimize the code length. Anyone have any ideas?

still a few lines:
n = 5; %number of elements
A(cumsum(0:n)+1) = 1;
B = cumsum(A(1:end-1))
returns
1 2 2 3 3 3 4 4 4 4 5 5 5 5 5

In the same spirit, here's my one liner:
nonzeros(triu(meshgrid(1:n)))'

n = 5;
A = triu(ones(n,1)*(1:n));
A(A==0) = [];

This is similar to jkshah's answer, but I would approach it slightly differently,
n=5;
M = ones(n,1)*(1:n)
B = M(triu(ones(n))>0)';

Here's another one-liner. Unlike solutions based on triu, this one doesn't generate extra elements as intermediate results (that doesn't mean it's faster, though):
fliplr(cumsum([n full(sparse(ones(1,n-1),cumsum(n:-1:2),-1))]))

A little 'magic' solution:
ceil(sqrt(2*(1:(n^2+n)/2))-0.5)
See visualisation:
This is the plot of function sqrt(2*(1:(n^2+n)/2))-0.5:
plot(1:(n^2+n)/2,sqrt(2*(1:(n^2+n)/2))-0.5,'.')
where xticklabels were changed according the following code:
set(gca,'xtick',cumsum(0:n),'xticklabel',0:n)

it is a litle bit longer
function y = your_fcn_name(n)
N = sum(1:n);w = [] ;
for i=1:n
q(1:i) = i;
w = [w q(1:i)];
end
y = w;
end

Related

Fast way to generate matrix of sampled rows with or without replacement in MATLAB

I have some input row. To perform some numerical statistical tests I need a lot of samples of the same size, which are sampled from the input row with or without replacement. I have some very straightforward code, which do it:
inputRow = [1 3 4 2 7 5 8 6];
rowSize = numel(inputRow);
nPermutations = 10;
permutedMatrix = nan(nPermutations,rowSize);
replaceFlag = true;
permutedMatrix(1,:) = inputRow;
for iPerm = 2:nPermutations
permutedMatrix(iPerm,:) = datasample(inputRow,rowSize,'Replace',replaceFlag);
end
My question is: Is it possible to generate desired matrix without for loops?
I hope this helps,
resampling with replacement:
input=[2 3 4 2 3 4];
len=size(input,2);
number_of_permutations=10;
rand_idx=randi(len,1,len*number_of_permutations);
permutation_matrix=zeros(len,number_of_permutations);
permutation_matrix(:)=input(rand_idx);
permutation_matrix=permutation_matrix';
this is reampling without replacement
input=[2 3 4 2 3 4];
len=size(input,2);
number_of_permutations=10;
rand_idx=repmat(randperm(len,len),1,number_of_permutations);
permutation_matrix=zeros(len,number_of_permutations);
permutation_matrix(:)=input(rand_idx);
permutation_matrix=permutation_matrix';

Insert embeded number in a vector matlab

Hey everyone I would like to do the following. I have a vector f.e. [1 2 3 4 6 8] and I want to end up in that vector [1 2 3 4 5 6 7 8] but generally, not like [v(1:4) 5 v(6) 7 v(8)].
Thank you very much!!
If you know your vector is going to be sorted you can use:
a = [1 2 3 4 6 8]; then
a = sort([a,5,7]);
This appends the additional values to the vector, sorts them, and assigns the sorted vector to the original variable.
Since the question is too vague, I'm not sure that I understand correctly, but this is what I came up with
If you have array to be modified
a = [a_1, ..., a_n]
and you want to insert
b = [b_1, ..., b_m]
and the position you want to insert
b_pos = [p_1, ..., p_m]
Then
n = length(a);
m = length(b);
a_pos = setdiff(1:(n+m),b_pos) % find index which is not included in b_pos
c = zeros(1,n+m);
c(a_pos) = a;
c(b_pos) = b;

Exporting matrix with Logical indexing in Matlab

I trying to export logical 1 indices of a matrix to another variable without altering their position. Below I am trying to explain my doubt using a example:
l = logical([1 0 1 1 ;...
1 1 1 0]);
A = [1 2 3 4;...
5 6 7 8];
B = zeros(size(A));
B = A(l)
produces:
B =
1
5
6
3
7
4
But what I am interested in getting is
B =
1 0 3 4
5 6 7 0
Can anyone help me? Thanks
While you could use #tim's approach for this specific example, a more general solution is to use the logical array to index both the thing you're retrieving values from and the array you're assigning into. This grabs the values in A at the TRUE locations in I and places them into the corresponding positions in B.
I = logical([1 0 1 1; 1 1 1 0]);
A = [1 2 3 4; 5 6 7 8];
B = zeros(size(A));
B(I) = A(I);
The element-wise multiplication approach won't work if you want the "default" values in B to be anything other than 0. For example.
% Initialize B to an array of 100's
B = 100 * ones(size(A));
% Replace the elements specified by the logical array
B(I) = A(I);
% 1 100 3 4
% 5 6 7 100
Alternately, if you just want to zero-out the values in A you can also use logical indexing to do this.
A(~I) = 0;
As a sidenote, try to avoid using l for a variable name as it is very difficult to distinguish l from the number 1.
l = logical([1 0 1 1 ;...
1 1 1 0]);
A = [1 2 3 4;...
5 6 7 8];
A .* l % element-wise multiplication
no prob, you are welcome ;-) Accept, question closed! xD
EDIT
I'm afraid Stackoverflow became a page where everyone tries to beat other's answers by trying to make a longer and more detailed answer, even though not related to WHAT WAS ORIGINALLY ASKED. And not the one's which give a quick, easy, simple solution within a small amount of time, to exactly that SPECIFIC QUESTION. Suever immediately becomes an upvote by answering a question which was NOT asked, just because it is longer.
I'll also play the game and edit my answer: If you want to have other default options then 0, one could also adopt my solution and use:
~l*default_value + A.*l
I just want to say: It IS possible.
EDIT2
tic;
for i = 1:1000000
B = A.*l;
end;
toc
>> Elapsed time is 2.18214 seconds.
tic;
for i = 1:1000000
B=zeros(size(A));
B(l)=A(l);
end;
toc
>>Elapsed time is 13.9691 seconds.
Choose for yourself.
EDIT3 (Default value != 0)
>> tic; for i = 1:1e6; B = A.*l+100*(~l); end; toc
Elapsed time is 4.17261 seconds.
>> tic; for i = 1:1e6; B=100*ones(size(A)); B(l)=A(l); end; toc
Elapsed time is 14.2126 seconds.

Unmatched arrays extending in Matlab

I wrote a code but when i am trying to change the variable schedule(2,:) it gives error. Here's the code:
clc;clear;
a = [1 2 3 4];
N = 3;
c=[1:12];
schedule(1,:) = kron(a,ones(1,N));% repeat 4 days
schedule(2,:) = repmat([1 2 3],1,((numel(c)/length(a)))+1); % repeat time slots in each day %nums col rep
schedule(3,:) = randperm(c(1,end)); % randomize 12 courses
schedule
I need a way of matching lengths of schedule(2,:) with other rows. When length of other rows is 20, schedule(2,:) does not build more than 20.
clc;clear;
day = [1 2 3 4];
n=length(day);
time=[1 2 3];
a=length(time);
schedule(1,:) = kron(day(1):n,ones(1,a));
schedule(2,:) = repmat(time,1,n);
schedule(3,:) = randperm(120,length(schedule(2,:)));
schedule
i have completed my code myself haha :) it is aflexible matrix and can accept any changes awithout errors

Recurring Function with Matrix Input

I believe most functions in MATLAB should be able to receive matrix input and return the output in the form of matrix.
For example sqrt([1 4 9]) would return [1 2 3].
However, when I tried this recurring factorial function:
function k = fact(z)
if z ~= 0
k = z * fact(z-1);
else
k = 1;
end
end
It works perfectly when a number is input into fact. However, when a matrix is input into fact, it returns the matrix itself, without performing the factorial function.
E.g.
fact(3) returns 6
fact([1 2 3]) returns [1 2 3] instead of [1 2 6].
Any help is appreciated. Thank you very much!
Since MATLAB is not known to be good with recursive functions, how about a vectorized approach? Try this for a vector input -
mat1 = repmat([1:max(z)],[numel(z) 1])
mat1(bsxfun(#gt,1:max(z),z'))=1
output1 = prod(mat1,2)
Sample run -
z =
1 2 7
output1 =
1
2
5040
For the sake of answering your original question, here's the annoying loopy code for a vector or 2D matrix as input -
function k1 = fact1(z1)
k1 = zeros(size(z1));
for ii = 1:size(z1,1)
for jj = 1:size(z1,2)
z = z1(ii,jj);
if z ~= 0
k1(ii,jj) = z .* fact1(z-1);
else
k1(ii,jj) = 1;
end
end
end
return
Sample run -
>> fact1([1 2 7;3 2 1])
ans =
1 2 5040
6 2 1
You can use the gamma function to compute the factorial without recursion:
function k = fact(z)
k = gamma(z+1);
Example:
>> fact([1 2 3 4])
ans =
1 2 6 24
Not sure if all of you know, but there is an actual factorial function defined in MATLAB that can take in arrays / matrices of any size, and computes the factorial element-wise. For example:
k = factorial([1 2 3 4; 5 6 7 8])
k =
1 2 6 24
120 720 5040 40320
Even though this post is looking for a recursive implementation, and Divakar has provided a solution, I'd still like to put my two cents in and suggest an alternative. Also, let's say that we don't have access to factorial, and we want to compute this from first principles. What I would personally do is create a cell array that's the same size as the input matrix, but each element in this cell array would be a linear index array from 1 up to the number defined for each location in the original matrix. You would then apply prod to each cell element to compute the factorial. A precondition is that no number is less than 1, and that all elements are integers. As such:
z1 = ... ; %// Define input matrix here
z1_matr = arrayfun(#(x) 1:x, z1, 'uni', 0);
out = cellfun(#prod, z1_matr);
If z1 = [1 2 3 4; 5 6 7 8];, from my previous example, we get the same output with the above code:
out =
1 2 6 24
120 720 5040 40320
This will obviously be slower as there is an arrayfun then cellfun call immediately after, but I figured I'd add another method for the sake of just adding in another method :) Not sure how constructive this is, but I figured I'd add my own method and join Divakar and Luis Mendo :)