Using Matlab to write a sequence - matlab

I'm struggling to write this question into Matlab Code. I know that I should use a 'for' loop, but I don't know how to use this to do it.
Consider the following sequence of row vectors v(n) for n ≥ 1:
v(1) = (1)
v(2) = (1, 1)
v(3) = (2, 1)
v(4) = (1, 2, 1, 1)
v(5) = (1, 1, 1, 2, 2, 1)
v(6) = (3, 1, 2, 2, 1, 1)
Each row is given by reading out the contents of the row above, so for example v(6) contains “three ones, two twos, one one” and this gives v6. Write a script to print v(n) for n = 1 up to n = 12.

One possible version:
N = 6;
v = cell(N,1);
v{1} = 1;
for ii = 2:N
v1 = v{ii-1};
stop_point = find(diff(v1));
if isempty(stop_point)
n = length(v1);
m = v1(1);
v{ii} = [n,m];
else
n = diff([0,stop_point,length(v1)]);
m = v1([stop_point,end]);
v2 = [n;m];
v{ii} = v2(:).';
end
end
Example output:
>> v{:}
ans =
1
ans =
1 1
ans =
2 1
ans =
1 2 1 1
ans =
1 1 1 2 2 1
ans =
3 1 2 2 1 1
>>
Note: Row vectors of unequal lengths cannot be contained in a matrix. An easy way to store them is using a cell array.

Related

How can I index multiple array segments at once without a loop?

I want to change the value in column 2 based on the values in column 1 in one array (main), using a start and end index from another array (conditions).
In conditions column 1 holds the start index, column 2 the end index.
main = zeros(8, 2);
main(:, 1) = 1:8;
conditions = [2, 3; 6, 8]
main =
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
conditions =
2 3
6 8
I know how to do it using a loop (shown below), but am looking for a faster method.
for ii = 1:size(conditions, 1)
main(main(:, 1) >= conditions(ii, 1) & main(:, 1) <= conditions(ii, 2), 2) = 1;
end
main =
1 0
2 1
3 1
4 0
5 0
6 1
7 1
8 1
Doing main(main(:, 1) >= conditions(:, 1) & main(:, 1) <= conditions(:, 2), 2) = 1 results in the error Matrix dimensions must agree.
Is there a non-loop method?
Your attempt is almost correct. If you transpose the conditions, then you'll be comparing a column of main with a row of conditions, leading to MATLAB doing implicit singleton expansion, giving a matrix output. This matrix can then be collapsed using any.
main = zeros(8, 2);
main(:, 1) = 1:8;
conditions = [2, 3; 6, 8];
index = (main(:,1) >= conditions(:, 1).') & (main(:, 1) <= conditions(:, 2).');
index = any(index,2);
main(index,2) = 1;
(I've separated out the code into 3 lines for clarity, but of course they can all be a single line.)
Note that for versions of MATLAB prior to R2016b, this code won't work, you'll need to use bsxfun instead:
index = bsxfun(#ge,main(:,1),conditions(:, 1).') & bsxfun(#le,main(:, 1),conditions(:, 2).');
NOTE: This is a solution for integers only as the original question only presented the integer case.
First, figure out how many elements there are included in the interval
dCon = diff(conditions,[],2)+1;
Then construct an increasing sequence of indexes to the maximum number of elements (this list would be enormous for the float case, and thus this solution does not, feasibly/efficiently, extend to floats)
idx0 = repmat(1:max(dCon),length(dCon),1);
Cap off the indexes that are too large
idx0(idx0>dCon)=1;
Now add the starting point
idx = idx0 + conditions(:,1)-1;
now idx contains all the numbers you want to change. Use ismember to find all elements in main and change them to 1.
main(ismember(main(:,1),idx(:)),2)=1;
EDIT: This is the full example with the vector from Gnovice in the comments
main = zeros(10, 2);
main(:, 1) = [1; 2; 2; 2; 3; 3; 4; 6; 6; 8];
conditions = [2, 3; 6, 8]
dCon = diff(conditions,[],2)+1;
idx0 = repmat(1:max(dCon),length(dCon),1);
idx0(idx0>dCon)=1;
idx = idx0 + conditions(:,1)-1;
main(ismember(main(:,1),idx(:)),2)=1;

How to permutate over columns for each row in a matrix in MATLAB?

I have a matrix
A = [1,2;3,4];
I would like to generate a new matrix B, which contains all permutations over the columns for each row.
B = [1,2;2,1;3,4;4,3]
Is there a one-liner solution?
I could only think of a solution incorporating cell arrays, thus I'm not sure, if that is "efficient" at all. Also, have a look at the limitations of perms.
% Input.
A = [1, 2; 3, 4]
% Expected output.
B = [1, 2; 2, 1; 3, 4; 4, 3]
% Calculate output.
C = sortrows(cell2mat(cellfun(#(x) perms(x), mat2cell(A, ones(1, size(A, 1)), 2), 'UniformOutput', false)))
A =
1 2
3 4
B =
1 2
2 1
3 4
4 3
C =
1 2
2 1
3 4
4 3
I found a solution to my own question.
n = 2; % size of permutations
perm_index = perms(1:n); % index of the matrix to perm
perm_length = size(perm_index,1);
data = [3,4;5,6];
data_length = size(data,1);
output_length = perm_length* data_length;
output = reshape(data(:,perm_index), output_length,n);
%Final output
output = [4,3;6,5;3,4;5,6]
I couldn't find any one-liner solution. Hope this one is simpler enough:
A = [1, 2, 3; 4, 5, 6];
B = [];
for i=1:size(A,1)
B = [B ; perms(A(i, :))];
end
Read about the function nchoosek
A = [1 2 3 4] ;
B = nchoosek(A,2)

Matlab: interpolation operator for multigrid methods

I have to build the following matrix:
1 2 1
1 2 1
1 2 1
I tried the following:
N = 8;
full( ( spdiags(repmat([1/4,1/2,1/4], N/2-1, 1), 0:2, N/2-1, N-1) ) )
but the output is not what I want.
It is not clean but it should work anyway:
N = 10;
w(1, :) = [1, 2, 1, zeros(1, (N-1)-3)];
for i = 1:(N/2-2)
w(i+1, :) = [zeros(1, i*2), 1, 2, 1, zeros(1, (N-1)-(3+i*2))];
end
I'm sure this could be condensed a bit, but here's a solution without loops. Assuming h is the grid spacing and N=1/h-1 is odd:
wdiag = 2*ones(N,1);
wsubsuperdiag = ones(N,1);
w = spdiags([wsubsuperdiag wdiag wsubsuperdiag],[-2 -1 0],N,(N+1)/2-1);
w = 1/2*cell2mat(arrayfun(#(k) circshift(w(:,k),k-1),1:(N+1)/2-1,'uni',0));
Some credit to Jon.

How to loop two vectors in MATLAB?

In python one can use zip to loop multiple vectors or enumerate to get the current index of the looped vector like so
one = ['A', 'B', 'C']
two = [1, 2, 3]
for i, j in zip(one, two):
print i, j
for j, i in enumerate(one):
print i, two[j]
Gives
>>>
A 1
B 2
C 3
A 1
B 2
C 3
In MATLAB it's possible to do
one = {'A' 'B' 'C'};
two = [1 2 3];
for i = 1:1:length(one)
printf('%s %i\n', one{i}, two(i));
endfor
j = 1;
for i = one
printf('%s %i\n', i{1}, two(j));
j = j + 1;
endfor
giving
A 1
B 2
C 3
A 1
B 2
C 3
So is one of those two options the common way how one would do it in MATLAB, i. e. to loop through several vectors "in parallel" or is there another, maybe better way?
Bonus:
two = [1 2 3];
two = [1, 2, 3];
Both of these lines give the same output in the upper MATLAB program. Whats the difference?
Using printf, or fprintf in Matlab, is pretty good. The Matlab code for your first approach is
one = {'A' 'B' 'C'};
two = [1 2 3];
for ii = 1:length(one)
fprintf('%s %i\n', one{ii}, two(ii));
end
It's also possible to put the strings into a cell array, without any for loop.
s = cellfun(#(a,b) [a,' ',b], one', ...
arrayfun(#num2str, two', 'UniformOutput', false),....
'UniformOutput', false)
Bonus:
>> A = [1;2;3]
A =
1
2
3
>> A = [1 2 3]
A =
1 2 3
>> A = [1,2,3]
A =
1 2 3
>> A = [1,2,3;4 5 6;7,8 9]
A =
1 2 3
4 5 6
7 8 9
>>
Bonus 2:
Using i and j is bad. See - Using i and j as variables in Matlab

Make matrix from shifted vector matlab vectorization

Geetings, here's the little problem.
I have a vector v (size(v) = T), a positive number P, P < T nad positive number N, N < T. And want to make matrix M with size PxN, so that:
M = [v(T), v(T-1), ....., v(T-N+2), v(T-N+1);
v(T-1), v(T-2), ....., v(T-N+1), v(T-N) ;
v(T-2), v(T-3), ....., v(T-N), v(T-N-1);
. . . . . ;
. . . . . ;
v(T-P+1), v(T-P), ....., v(T-P-N+3), v(T-P-N+2)]
It holds that T > P + N.
Let given an example.
v = [1, 2, 3, 4, 5]';
P = 3;
N = 3;
M = [5, 4, 3;
4, 3, 2;
3, 2, 1]
I know how to do this using for loop, but I also think that it is possible do by vectorizations - here the problem is - I am not so skilled in vectorizations.
Thx for hints and so on :))
Use the Hankel matrix:
v = [1 2 3 4 5];
T = length(v);
P = 3;
N = 3;
out = hankel(v(T:-1:T-P+1),v(T-P+1:-1:T-P-N+2));
You can make use of bsxfun
v = [1, 2, 3, 4, 5]';
P = 3;
N = 3;
idx = bsxfun(#minus, length(v):-1:length(v)-N+1, (0:P-1)');
result = v(idx);
this will result in
result =
5 4 3
4 3 2
3 2 1