0

I have two input variables:

N=10;
M=4;

Using Matlab, I want to generate the following matrices - without using for loops, for any M and N:

    %N = 1   2   3   4   5   6   7   8  9
Mat1 = [2,  3,  4,  5,  6,  7,  8,  9, 10;      %M=1 -> Mat1(1, i) = N(i)+1
        3,  6,  9, 12, 15, 18, 21, 27, 30;      %M=2 -> Mat1(2, i) = N(i)+N(i)*2
        4,  8, 12, 16, 20, 24, 28, 32, 36;      %M=3 -> Mat1(2, i) = N(i)+N(i)*3
        5, 10, 15, 20, 25, 30, 35, 40, 45]      %M=4 -> Mat1(2, i) = N(i)+N(i)*4

   %N = 1   2   3   4   5   6   7   8  9
Mat2 = [1, 2,  3,  4,  5,  6,  7,  8,  9;       %M=1 -> Mat2(2, i) = N(i)
        1, 4,  7, 10, 13, 16, 19, 25, 28;       %M=2 -> Mat2(2, i) = N(i)+N(i)*2-2
        1, 5,  9, 13, 17, 21, 25, 29, 33;       %M=3 -> Mat2(2, i) = N(i)+N(i)*3-3
        1, 6, 11, 16, 21, 26, 31, 36, 41]       %M=4 -> Mat2(2, i) = N(i)+N(i)*4-4

General description:

% i=1:N

%Mat1(M, i) = N(i)+N(i)*M    , if M>1
%             N(i)+1         , if M=1

%Mat2(M, i) = N(i)+N(i)*M-M  , if M>1
%             N(i)           , if M=1

I wrote a code with two for loops, but I would like to ask if there is any method to get these results, without using loops. I tried with bsxfun and arrayfun, but I did not manage to get the right result:

clear Mat1 Mat2
N=10;
M=9;

Mat1 = ones(M, N);
Mat2 = ones(M, N);
for i=1:M
    for j=1:N
        if  i==1
            Mat1(i, j) = j+1;
            Mat2(i, j) = j;
        elseif j ==1  
            Mat1(i, j) = j+j*i;
        elseif i~=1 && j~=1
            Mat1(i, j) = j+j*i;
            Mat2(i, j) = j+j*i-i;
        end
        
    end
end

Thank you

Community
  • 1
  • 1
uhnucross
  • 103
  • 1
  • 8
  • It is best [not to use `i` and `j` as variables in Matlab](http://stackoverflow.com/questions/14790740/using-i-and-j-as-variables-in-matlab). – Shai Feb 20 '13 at 11:16
  • 1
    Can you describe, in a more concise manner, what are the rules for generating `Mat1` and `Mat2`? – Shai Feb 20 '13 at 11:17
  • I made an update in the Mat1 and Mat2 comments – uhnucross Feb 20 '13 at 11:26

4 Answers4

3

My try:

N=10;
M=4;
mat1 = bsxfun(@(x,y) x*(y.*(y>1)+1)+(y==1), 1:N,(1:M)')
mat2 = bsxfun(@(x,y) x*(y.*(y>1)+1)-(y>1).*y, 1:N,(1:M)')
bdecaf
  • 4,652
  • 23
  • 44
1

I think this might do what you are looking for:

First matrix:

Mat1 = (2:N+1)'*(1:N);
Mat1 = Mat1(1:M,:);
Mat1(1,:) = 2:N+1;

This gives (N=10, M=4):

Mat1 =

 2     3     4     5     6     7     8     9    10    11
 3     6     9    12    15    18    21    24    27    30
 4     8    12    16    20    24    28    32    36    40
 5    10    15    20    25    30    35    40    45    50

Second matrix:

tmp = (0:N-2)'*(1:N-1);
Mat2 = repmat((4:3:3*N),M-1,1) + tmp(1:M-1,:);
Mat2 = [ones(M,1), [2:N; Mat2]];

Which gives:

Mat2 =

 1     2     3     4     5     6     7     8     9    10
 1     4     7    10    13    16    19    22    25    28
 1     5     9    13    17    21    25    29    33    37
 1     6    11    16    21    26    31    36    41    46

It was a bit of a puzzle, as it is not all too clear what exactly are the rules to build these matrices. But if it is just these matrices you want, this should be a fast way to get them.

For all N and M these lines of code produce the same matrices as you code with for loops does.

ThijsW
  • 2,599
  • 15
  • 17
  • For `Mat1` you haven't posted the result of executing your own code but a version which omits the line `Mat1(1,:) = 2:N+1`. Both your outputs have 10 columns, OP's examples only have the first 9. – High Performance Mark Feb 20 '13 at 13:18
  • @HighPerformanceMark You are right, I changed it to the correct output. And I just figured `N` is supposed to be the number of columns, but of course the last column could be omitted if desired. Or replacing `N` by `N-1` will do the trick. – ThijsW Feb 20 '13 at 13:35
1

Meanwhile I learned how to use bsxfun and repmat. I got a compact code for both Mat1 and Mat2 generators:

N=10;
M=4;

Mat1 = bsxfun(@times, (1:M)', (1:N)) +...
      [ones(1, N)  ;  horzcat(  ones(M-1,1) , repmat(2:N,M-1,1)   )   ];

Mat2 = [ones(M,1), [(2:N); bsxfun(@plus, (2:M)',(2:N)) +...
        horzcat(  zeros(M-1,1),  bsxfun(@times, (2:M)',(1:N-2))  )   ] ];

Mat1 =

 2     3     4     5     6     7     8     9    10    11
 3     6     9    12    15    18    21    24    27    30
 4     8    12    16    20    24    28    32    36    40
 5    10    15    20    25    30    35    40    45    50

Mat2 =

 1     2     3     4     5     6     7     8     9    10
 1     4     7    10    13    16    19    22    25    28
 1     5     9    13    17    21    25    29    33    37
 1     6    11    16    21    26    31    36    41    46
uhnucross
  • 103
  • 1
  • 8
0

I haven't tried these for every test case so I am not sure if it's totally general. I think you should be able to investigate what I used to do this and arrive at a solution for the first matrix as well. I think you might have some typos in your sample matrices above, hopefully this will get you on the right track

 M=4;
 N=10;

 Mat2=repmat([1:N],M,1);
 Mat2(2:M,:)=Mat2(2:M,:)+bsxfun(@times, Mat2(2:M,:), [2:M]');
 Mat2(2:M,:)=bsxfun(@minus, Mat2(2:M,:), [2:M]');

gives us:

Mat2 =

 1     2     3     4     5     6     7     8     9    10
 1     4     7    10    13    16    19    22    25    28
 1     5     9    13    17    21    25    29    33    37
 1     6    11    16    21    26    31    36    41    46

with M=5 and N=10

Mat2 =

 1     2     3     4     5     6     7     8     9    10
 1     4     7    10    13    16    19    22    25    28
 1     5     9    13    17    21    25    29    33    37
 1     6    11    16    21    26    31    36    41    46
 1     7    13    19    25    31    37    43    49    55

and I think this is Mat1:

 Mat1=repmat([1:N],M,1);
 Mat1(2:M,:)=Mat1(2:M,:)+bsxfun(@times, Mat1(2:M,:), [2:M]');
 Mat1(1,:)=Mat1(1,:)+1;

Mat1 =

 2     3     4     5     6     7     8     9    10    11
 3     6     9    12    15    18    21    24    27    30
 4     8    12    16    20    24    28    32    36    40
 5    10    15    20    25    30    35    40    45    50
johnish
  • 390
  • 5
  • 13