MATLAB: How to make a matrix of values based on values in another matrix

matrix array

Hi,
I am trying to make a matrix based on the values in the matrix below. The first column of values needs to be negative, while the second column of values remains positive. The '1' in column 1 (and in column 2 if there were any) also needs to be removed entirely.
The placing of the values are also based on what the value initially is. In the second column, value 2 needs to be put in columns 1 and 2. Value 3 needs to be put in columns 3 and 4, so on so forth. The same applies for the first column, except they're negative.
The value '1' however is completely ignored.
The output should look something like this:
The part that I feel makes this task even more impossible is that this has to work 'universally'. Below is another example:
Input: [ 1 3 ; 2 3 ; 2 4 ; 4 1 ; 2 1 ]
Output: [ 0 0 3 3 0 0 ; -2 -2 3 3 0 0 ; -2 -2 0 0 4 4 ; 0 0 0 0 -4 -4 ; -2 -2 0 0 0 0 ]
I look forward to answers regarding this abomination.

Best Answer

The trick is to use sub2ind, and remember that MATLAB operates down columns first, so it helps to transpose the input matrix. Note in the code below the indices idx, idc, idr, and idi refer to this transposed matrix.

>> M = [1,2;2,3;3,4;1,3;1,4]
M =
     1     2
     2     3
     3     4
     1     3
     1     4
>> tmp = M.';                   % because MATLAB operates down columns
>> idx = tmp~=1;                % input logical indices
>> [~,idc] = find(idx);         % output column indices
>> idr = tmp(idx)-1;            % output row indices
>> mat = zeros(max([idr,idc])); % preallocate the output matrix
>> idi = sub2ind(size(mat),idr,idc); % output linear indices
>> tmp(1,:) = -tmp(1,:); % first row negative (first column of M)
>> mat(idi) = tmp(idx);  % assign input values to output matrix
>> mat.' % all values present and correct!
ans =
     2     0     0
    -2     3     0
     0    -3     4
     0     3     0
     0     0     4

At this point you could simply use repelem or the method below:

>> mat = reshape(repmat(mat.',2,1),size(mat,2),[])
mat =
     2     2     0     0     0     0
    -2    -2     3     3     0     0
     0     0    -3    -3     4     4
     0     0     3     3     0     0
     0     0     0     0     4     4

Here I tested the code on your other sample matrix:

>> M = [1,3;2,3;2,4;4,1;2,1]
M =
     1     3
     2     3
     2     4
     4     1
     2     1
...
>> mat = reshape(...)
mat =
     0     0     3     3     0     0
    -2    -2     3     3     0     0
    -2    -2     0     0     4     4
     0     0     0     0    -4    -4
    -2    -2     0     0     0     0

which can be compared against your requested output:

>> [ 0 0 3 3 0 0 ; -2 -2 3 3 0 0 ; -2 -2 0 0 4 4 ; 0 0 0 0 -4 -4 ; -2 -2 0 0 0 0 ]
ans =
     0     0     3     3     0     0
    -2    -2     3     3     0     0
    -2    -2     0     0     4     4
     0     0     0     0    -4    -4
    -2    -2     0     0     0     0