2015-11-17 13 views
12

Angenommen, ich habe einen symmetrischen Zeilenvektor mit einer ungeraden Länge, wobei jedes Element kleiner als das nächste in der ersten Hälfte des Vektors ist und jedes Element größer als das nächste in der zweiten ist halb und das mittlere Element ist das größte. (z.B. [1 2 3 2 1] oder [10 20 50 20 10]).Erstellen Sie eine "Pyramide" -Matrix

Ich möchte eine quadratische Matrix erstellen, wo dieser Zeilenvektor seine mittlere Zeile ist und der äquivalente Spaltenvektor (v') seine mittlere Spalte und jede andere Zeile oder Spalte eine reduzierte Version des angegebenen Vektors gemäß dem mittleren Element ist in dieser Zeile oder Spalte. Und wenn es keine "ursprünglichen Elemente" mehr gibt, setzen wir 0.

Beispiele:

wenn v = [1 2 3 2 1] wir

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 

wenn v = [3 5 3] wir

0 3 0 
3 5 3 
0 3 0 

bekommen bekommen, was ich bisher tat ich es geschafft, eine Matrix mit v als der mittleren Reihe zu erstellen und v' als die mittlere Spalte mit diesem Code schrieb ich:

s = length(vector); 
matrix= zeros(s); 
matrix(round(s/2),:) = vector; 
matrix(:, round(s/2)) = vector'; 

aber blieb bei der Zuweisung der anderen Werte stecken.

Antwort

8

Ein Hands-on-Ansatz ist zu produzieren Ihre Matrix als Mosaik, ausgehend von einer hankel Matrix. Für Performance-Vergleich, hier ist eine Version das gleiche Format wie @Divakar's solution mit:

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 

für v=[1 2 3 2 1] der Startblock ist hankel([3 2 1]), die

ans = 

    3  2  1 
    2  1  0 
    1  0  0 

Von hier aus ist, sollte klar sein, was ist Ereignis.

+1

@Adrian und @AndrasDeak: die 'hankel' Funktion verwendet' bsxfun' intern. – horchler

+0

Oh, nicht! Die Art, wie ich 'bsxfun' benutze, ist nicht ähnlich wie 'hankel' mit 'bsxfun' implementiert wurde. AFAIK hankel hat 'bsxfun (@ plus'. – Divakar

8

Hier ist ein Ansatz -

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); 

hier ein anderer Ansatz ist, eine Art vielleicht einfacher -

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); 

Beispielläufe -

>> 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 
+0

Während meine Antwort leichter schmackhaft scheint, erwarten Sie entweder einigermaßen schneller für große Probleme zu sein? –

+0

Wegen der Neugier habe ich Ihre zwei Methoden zur Berechnung der Geschwindigkeit überprüft: @AndrasDeak - 0,055571; Divakar - 0,03777. Aber Jungs! Deine Gedankengeschwindigkeit bringt mich um - ich sehe diese Frage und berechne bereits Formeln für alle notwendigen Diagonalen und versuche sie zu implementieren, reibe meine Handflächen ... Und du hast bereits deine Antworten gepostet, die meinen Verstand blind machen, es ist Eleganz. Ich kann immer noch nicht in Matrixform denken, nicht in Form von Schleifen :) –

+0

@Mikhail_Sam Schätze die Bemühungen beim Benchmarking! Also, der, den du getestet hast, war der '_v2', oder?Vielen Dank auf Ihre Wertschätzung :) – Divakar

5

Hier ist ein weiterer Ansatz:

v = [1 2 3 2 1]; %// symmetric, odd size 
m = (numel(v)-1)/2; 
w = [0 v(1:m+1)]; 
t = abs(-m:m); 
result = w(max(m+2-bsxfun(@plus, t, t.'),1));