2015-11-17 19 views
12

Dire che mi viene assegnato un vettore di riga simmetrico con una lunghezza dispari in cui ogni elemento è più piccolo del successivo nella prima metà del vettore e ogni elemento è più grande di quello successivo nel secondo la metà e l'elemento centrale è il più grande. (ad esempio [1 2 3 2 1] o [10 20 50 20 10]).Creare una matrice "piramide"

Voglio creare una matrice quadrata in cui questo vettore riga è la riga centrale e il vettore colonna equivalente (v') è la sua colonna centrale e ogni riga o colonna è una versione ridotta del vettore specificato in base all'elemento centrale in questa riga o colonna. E quando non ci sono più "elementi originali", inseriamo 0.

Esempi:

se v = [1 2 3 2 1] otteniamo

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 

se v = [3 5 3] otteniamo

0 3 0 
3 5 3 
0 3 0 

Quello che ho fatto finora: sono riuscito a creare una matrice con v come la fila centrale e v' come colonna centrale con questo codice che ho scritto:

ma si è bloccato con l'assegnazione degli altri valori.

risposta

8

Un altro approccio pratico è quello di produrre la matrice come mosaico, a partire da una matrice hankel. Per il confronto delle prestazioni, ecco una versione utilizzando lo stesso formato @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 

Per v=[1 2 3 2 1] blocco di partenza è hankel([3 2 1]), che è

ans = 

    3  2  1 
    2  1  0 
    1  0  0 

Da qui dovrebbe essere chiaro che cosa è accadendo.

+1

@Adrian e @AndrasDeak: la funzione 'hankel' usa' bsxfun' internamente. – horchler

+0

Oh no! Il modo in cui sto usando 'bsxfun' non è simile a come' hankel' è implementato usando 'bsxfun'. AFAIK hankel ha' bsxfun (@ plus'. – Divakar

8

Ecco uno approccio -

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

Ecco un altro approccio, una sorta di semplice forse -

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

piste del campione -

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

Mentre la mia risposta sembra più facilmente appetibile, cosa si aspetta sia per essere ragionevolmente veloce per problemi di grandi dimensioni? –

+0

A causa della curiosità ho controllato i tuoi due metodi per la velocità di calcolo: @AndrasDeak - 0.055571; Divakar - 0,03777. Ma ragazzi! La tua velocità mi sta uccidendo - Vedo questa domanda e già calcolo le formule per tutte le diagonali necessarie e cerco di implementarla, stropicciandosi i palmi ... E hai già postato le tue risposte che accecano la mia mente è eleganza. Non riesco ancora a iniziare a pensare in forma di matrice non in forma di loop :) –

+0

@Mikhail_Sam Apprezzare gli sforzi sul benchmarking! Quindi, quello che hai provato era quello di '_v2', giusto?Grazie per il tuo apprezzamento :) – Divakar

5

Ecco un altro approccio:

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