3
votes

If I have a vector

A = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]

Is there any way to convert this to a matrix

[0   2   5   9   14 
 1   4   8   13  0
 3   7   12  0   0
 6   11  0   0   0
 10  0   0   0   0 ]

For vector A of length 2016.

So far:

n = 63;
B = triu(true(n));
C = zeros(n);
C(B) = A;

Looks to be on the right line.

Then to try and create vector D whereby each column is the diagonal of matrix C...

D = zeros(n);

for i = 1:n;
    D(:,i) = diag(C,i-1);
end

But on the second iteration the length of the diagonal does not fill an entire column (as expected and desired) and I get a dimension mismatch error.

2
So the last 4 elements become the first row, next-last 3 elements become the second row (with zero padding), next-last 2 elements become the third row (with zero padding) and so on?Wolfie
I have edited the question to make it more clear what I am after... sorry if it still isn't explained well! In reality i need to repeat this pattern for a matrix A of length 2016.Tom Haddow
It would help if you gave the actual result matrix with whatever filler values you want to use (or maybe you actually want a cell array?). The syntax you're showing is not legal in MATLAB.beaker
You cannot have a matrix with rows with different numbers of columns. You can only do that with a cell arrayWolfie
Possible duplicate of Matrix "Zigzag" Reorderingbeaker

2 Answers

4
votes

This assumes that the length of A is a triangular number, so that A can fit in half a square matrix including the diagonal:

N = (sqrt(numel(A)*8+1)-1)/2;
t = hankel(1:N);
t(t==0) = inf;
[~, ind]= sort(t(:));
ind = ind(1:numel(A));
result = zeros(N);
result(ind) = A;
4
votes

Here's one with some help from bsxfun and cumsum -

function out = zigzag_upward(A, n)
% If n is needed to be computed : n = floor(sqrt(numel(A)*2))
r = 1:n;
valid_mask = bsxfun(@le, r,r(end:-1:1)');
all_vals = cumsum([(cumsum(0:n-1)+1)' bsxfun(@plus,[0:n-1]',2:n)],2);
all_vals(all_vals > numel(A)) = 1;
out = valid_mask .* A(all_vals);

Sample run -

>> A = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]+20;
>> zigzag_upward(A, 5)
ans =
    20    22    25    29    34
    21    24    28    33     0
    23    27    32     0     0
    26    31     0     0     0
    30     0     0     0     0