views:

151

answers:

5

hi guys, im not not a programmer, i just need to solve something numerically in matlab. i need a function to make the following transformation for any square matrix:

from

row 1: 1 2 3 
row 2: 4 5 6
row 3: 7 8 9

to

1 4 2 7 5 3 8 6 9

ie write the matrix in a vector along its diagonals from left to top right. any ideas please?


i really need a little more help though:

say the matrix that we have transformed into the vector, has entries denoted by M(i,j), where i are rows and j columns. now i need to be able to find out from a position in the vector, the original position in the matrix, i.e say if its 3rd entry in the vector, i need a function that would give me i=1 j=2. any ideas please? im really stuck on this:( thanks

+3  A: 

Here's one way to do this.

%# n is the number of rows (or cols) of the square array
n = 3;
array = [1 2 3;4 5 6;7 8 9]; %# this is the array we'll reorder

%# create list of indices that allow us
%# to read the array in the proper order
hh = hankel(1:n,n:(2*n-1)); %# creates a matrix with numbered antidiagonals
[dummy,sortIdx] = sort(hh(:)); %# sortIdx contains the new order

%# reorder the array
array(sortIdx)

ans =
     1     4     2     7     5     3     8     6     9
Jonas
The call to BSXFUN is unnecessary. You can just do `sort(hh(:))` to get the index vector.
gnovice
Thanks, @gnovice
Jonas
+1  A: 
A=[1,2,3;4,5,6;7,8,9];
d = size(A,1);
X=[];
for n = 1:2*size(A,1) - 1
    j = min(n,d); i = (n+1)-(j);
    X = cat(2,X,diag(flipud(A(i:j,i:j)))');
end

X
X =
     1     4     2     7     5     3     8     6     9
gd047
+1  A: 

You can generate the diagonals in this way:

for i = -2:2
    diag(flipud(a), i)
end

I don't know whether this is the optimal way to concatenate the diagonals:

d = []
for i = -2:2
    d = vertcat(d, diag(flipud(a), i))
end

(I tested it in octave, not in matlab)

Roberto Bonvallet
+2  A: 

You can convert your matrix to a vector using the function HANKEL to generate indices into the matrix. Here's a shortened version of Jonas' answer, using M as your sample matrix given above:

N = size(M,1);
A = hankel(1:N,N:(2*N-1));
[junk,sortIndex] = sort(A(:));

Now, you can use sortIndex to change your matrix M to a vector vec like so:

vec = M(sortIndex);

And if you want to get the row and column indices (rIndex and cIndex) into your original matrix that correspond to the values in vec, you can use the function IND2SUB:

[rIndex,cIndex] = ind2sub(N,sortIndex);
gnovice
+6  A: 

This is quite similar to a previous question on traversing the matrix in a zigzag order. With slight modification we get:

A = rand(3);                        %# input matrix

ind = reshape(1:numel(A), size(A)); %# indices of elements
ind = spdiags(fliplr(ind));         %# get the anti-diagonals
ind = ind(end:-1:1);                %# reverse order
ind = ind(ind~=0);                  %# keep non-zero indices
B = A(ind);                         %# get elements in desired order

using the SPDIAGS function. The advantage of this is that it works for any arbitrary matrix size (not just square matrices). Example:

A =
      0.75127      0.69908      0.54722      0.25751
       0.2551       0.8909      0.13862      0.84072
      0.50596      0.95929      0.14929      0.25428
B =
  Columns 1 through 6
      0.75127       0.2551      0.69908      0.50596       0.8909      0.54722
  Columns 7 through 12
      0.95929      0.13862      0.25751      0.14929      0.84072      0.25428
Amro