Say I'm given a symmetric row vector with an odd length where each element is smaller than the next one in the first half of the vector and each element is bigger than the next one in the second half and the middle element is the biggest. (e.g [1 2 3 2 1]
or [10 20 50 20 10]
).
I want to create a square matrix where this row vector is its middle row and the equivalent column vector (v'
) is its middle column and each other row or column is a reduced version of the given vector according to the middle element in this row or column. And when there are no more "original elements" we put 0
.
Examples:
if v = [1 2 3 2 1]
we get
0 0 1 0 0
0 1 2 1 0
1 2 3 2 1
0 1 2 1 0
0 0 1 0 0
if v = [3 5 3]
we get
0 3 0
3 5 3
0 3 0
What I did so far: I managed to create a matrix with v
as the middle row and v'
as the middle column with this code I wrote:
s = length(vector);
matrix= zeros(s);
matrix(round(s/2),:) = vector;
matrix(:, round(s/2)) = vector';
but got stuck with assigning the other values.
A more hands-on approach is to produce your matrix as a mosaic, starting from a hankel
matrix. For performance comparison, here's a version using the same format as @Divakar's solution:
function out=pyramid_hankel(v)
%I suggest checking v here
%it should be odd in length and a palindrome
i0=ceil(length(v)/2);
v2=v(i0:end);
Mtmp=hankel(v2);
out=zeros(length(v));
out(i0:end,i0:end)=Mtmp;
out(1:i0-1,i0:end)=flipud(Mtmp(2:end,:));
out(:,1:i0-1)=fliplr(out(:,i0+1:end));
>> pyramid_hankel([1 2 3 2 1])
ans =
0 0 1 0 0
0 1 2 1 0
1 2 3 2 1
0 1 2 1 0
0 0 1 0 0
For v=[1 2 3 2 1]
the starting block is hankel([3 2 1])
, which is
ans =
3 2 1
2 1 0
1 0 0
From here it should be clear what's happening.
Here's one approach -
function out = pyramid(v)
hlen = (numel(v)+1)/2;
updown_vec = [1:(numel(v)+1)/2 (numel(v)-1)/2:-1:1];
upper_part = cumsum(bsxfun(@le,(hlen:-1:1)',updown_vec)); %//'
out = [upper_part ; flipud(upper_part(1:end-1,:))];
out = changem(out,v,updown_vec);
Here's another approach, sort of simpler maybe -
function out = pyramid_v2(v)
hlen = (numel(v)+1)/2;
updown_vec = [1:(numel(v)+1)/2 (numel(v)-1)/2:-1:1];
mask = bsxfun(@le,([hlen:-1:1 2:hlen])',updown_vec); %//'
M = double(mask);
M(hlen+1:end,:) = -1;
out = changem(cumsum(M).*mask,v,updown_vec);
Sample runs -
>> v = [1 2 3 2 1];
>> pyramid(v)
ans =
0 0 1 0 0
0 1 2 1 0
1 2 3 2 1
0 1 2 1 0
0 0 1 0 0
>> v = [3 5 3];
>> pyramid(v)
ans =
0 3 0
3 5 3
0 3 0
>> v = [99,3,78,55,78,3,99];
>> pyramid(v)
ans =
0 0 0 99 0 0 0
0 0 99 3 99 0 0
0 99 3 78 3 99 0
99 3 78 55 78 3 99
0 99 3 78 3 99 0
0 0 99 3 99 0 0
0 0 0 99 0 0 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With