CORSO DI LAUREA IN INGEGNERIA ELETTRICA Informatica B anno accademico 2012-2013 Prof. Danilo ARDAGNA Esercitazione – 23.05.2013 Esercizio 1. (Elemento piu' ripetuto - funzione a singolo parametro) Scrivere una funzione che, data una matrice, restituisce l'elemento che compare piu' spesso al suo interno. Soluzione Considero come elemento piu' ripetuto il primo elemento della matrice contato come ripetuto zero volte. Dopodiche' lo confronto con il numero di volte in cui tutti gli elementi (compreso il primo) sono compresi nella matrice. Se dal confronto risulta che un numero e' ripetuto piu' volte del precedente elemento considerato, allora lo sostituisco. Alla fine otterro' l'elemento che compare piu' spesso. Codice function [elem]=elemento_piu_ripetuto(m) elem = m(1,1); count = 0; [r c] = size(m); for ii=1:r for jj=1:c tmp_count = sum(sum(m==m(ii,jj))); if tmp_count>count elem = m(ii,jj); count = tmp_count; end end end Esecuzione >> elemento_piu_ripetuto([1 2 3; 3 4 5; 6 7 3]) ans = 3 Esercizio 2. (Costruzione matrici - funzione a piu' parametri) 2 Scrivere una funzione che, date due matrici A e B aventi stesse dimensioni, restituisca due matrici C e D in cui C contiene le righe di A o di B che hanno somma minore, mentre D contiene le colonne di A o di B che hanno somma maggiore. In caso di uguaglianza tra le somme si dia priorita' alle righe/colonne della matrice A. Esempio: INPUT: | OUTPUT: 1 2 3 9 8 7 | 1 2 3 9 8 3 A=4 5 4 B=1 1 1 | C=1 1 1 D=1 1 4 1 2 3 3 2 1 | 1 2 3 3 2 3 Soluzione Codice function [C D] = cotruiscimatrici(A,B) [nrighe ncolonne]=size(A); % uguale a size(B) C=zeros(nrighe,ncolonne); D=zeros(nrighe,ncolonne); % determino C for ii=1:nrighe if sum(A(ii,:))<=sum(B(ii,:)) C(ii,:)=A(ii,:); else C(ii,:)=B(ii,:); end end % determino D for ii=1:ncolonne if sum(A(:,ii))>=sum(B(:,ii)) D(:,ii)=A(:,ii); else D(:,ii)=B(:,ii); end end Esecuzione A = 1 4 1 2 5 2 3 4 3 9 1 3 8 1 2 7 1 1 >> B B = >> [C D]=costruiscimatrici(A,B) C = 1 2 3 1 1 1 1 2 3 D = 9 8 3 1 1 4 3 2 3 2 Esercizio 3. (Fattoriale vettorizzato) 3 Data la seguente funzione per il calcolo del fattoriale. Si dica se la funzione supporta la vettorizzazione. In caso di risposta negativa la si modifichi per supportarla. function [f]=fact(n) f=1; for k=1:n f=f*k; end Soluzione La funzione fact() proposta non supporta la vettorizzazione. Cioe' non e' possibile passare alla funzione come argomento una matrice e aspettarsi come risultato una matrice delle stesse dimensioni di quella data avente per elementi il fattoriale degli elementi corrispondenti della matrice originale. Codice function [f]=fact(n) [r c]=size(n); % scandisco tutti gli elementi di n for ii=1:r for jj=1:c % codice originale % sostituisco f con f(ii,jj) e n con n(ii,jj) f(ii,jj)=1; for k=1:n(ii,jj) f(ii,jj)=f(ii,jj)*k; end end end Esecuzione prima della modifica >> fact(5) ans = 120 >> fact(2:5) ans = 2 >> fact([2 3;4 5]) ans = 2 Esecuzione dopo la modifica >> fact(5) ans = 120 >> fact(2:5) ans = 2 6 24 >> fact([2 3;4 5]) ans = 2 6 24 120 120 3 4 Esercizio 4. (Sistemi di equazioni lineari) Si scriva uno script che chieda l'inserimento dei coefficienti e dei termini noti di un sistema di equazioni di primo grado in M equazioni e N incognite. Dopodiche' si calcoli la soluzione del sistema. Si consideri solo il caso in cui M e' uguale a N. Soluzione Il sistema puo' essere rappresentato in forma di matrice: Dall'algebra lineare sappiamo che i valori delle incognite che corrispondono alla soluzione del sistema sono contenuti nella matrice data dalla moltiplicazione dell'inverso della matrice dei coefficienti A per il vettore dei termini noti. La soluzione e' quindi S=A-1b che in Matlab equivale all'operazione di divisione sinistra: S=A\b Codice N=input('Inserire il numero di equazioni e di incognite: '); for x=1:N % righe (equazioni) for y=1:N % colonne (incognite) A(x,y)=input(['inserire coefficiente incognita ' num2str(y) . " " " " ' dell''equazione ' num2str(x) ': ']); end b(x)=input(['inserire termine noto equazione ' num2str(x) ': ']); end A b S=A\b' 4 5 Esecuzione inserire inserire inserire inserire inserire inserire inserire A = b = S = numero di equazioni e di incognite: 2 coefficiente incognita 1 dell'equazione coefficiente incognita 2 dell'equazione termine noto equazione 1: 4 coefficiente incognita 1 dell'equazione coefficiente incognita 2 dell'equazione termine noto equazione 2: -1 1 -6 2 5 4 -1 1: 1 1: 2 2: -6 2: 5 1.2941 1.3529 Esercizio 5. (Confronti - metodo senza ciclo for) Si scriva uno script che chiede di inserire una sequenza di N numeri, dopodiche' si inserisca un ulteriore numero e si dica se tutti i numeri della sequenza sono minori, uguali o maggiori di tale numero. Soluzione Sono presenti due modi per risolvere questo problema. Il secondo modo proposto evita l'utilizzo del costrutto for ed e' piu' efficiente e leggibile. Codice 1 N=input('inserire N: '); for x=1:N a(x) = input('inserire numero: '); end M=input('inserire M: '); minori=true; maggiori=true; uguali=true; for x=1:N if a(x)>M minori=false; uguali=false; elseif a(x)<M maggiori=false; uguali=false; else maggiori=false; minori=false; end end if minori disp('I numeri della sequenza sono minori del numero dato'); else disp('I numeri della sequenza non sono minori del numero dato'); 5 6 end if maggiori disp('I else disp('I end if uguali disp('I else disp('I end numeri della sequenza sono maggiori del numero dato'); numeri della sequenza non sono maggiori del numero dato'); numeri della sequenza sono uguali al numero dato'); numeri della sequenza non sono uguali al numero dato'); Codice alternativo (piu' efficiente) che sostituisce il ciclo for if sum(a<M) < N minori = false; end if sum(a>M) < N maggiori = false; end if sum(a==M) < N uguali = false; end Esecuzione inserire inserire inserire inserire inserire inserire inserire I numeri I numeri I numeri N: 5 numero: 1 numero: 2 numero: 3 numero: 4 numero: 5 M: 6 della sequenza sono minori del numero dato della sequenza non sono maggiori del numero dato della sequenza non sono uguali al numero dato Esercizio 6. (Matrici logiche misteriose) Date le seguenti matrici a e b si dica cosa stampano le seguenti istruzioni. a= 1 4 7 2 5 8 3 6 9 b= 9 6 3 8 5 2 7 4 1 1. a(3,1) 2. a(8) 3. a(a==b) 6 4. b(a>b|b>a) 5. c=a;c(a>b)=b(a>b).^2 6. find(mod(a,b)) 7. [r c]=find(mod(a,b)) 7 Soluzione 1 >> a(3,1) ans = 7 L'istruzione accede al valore memorizzato nella riga 3 e colonna 1 della matrice a. Soluzione 2 >> a(8) ans = 6 L'istruzione accede al valore memorizzato nell'ottavo elemento della matrice. Gli elementi vengono contati per colonna. La prima colonna ha i primi 3 elementi, la seconda colonna ha gli altri 3 e cosi' via fino al nono elemento. In questo caso l'ottavo elemento coincide con l'elemento della seconda riga e della terza colonna. Soluzione 3 >> a(a==b) ans = 5 Utilizzo il vettore logico generato dalla relazione a==b per selezionare gli elementi di a. In questo caso il vettore logico a==b e' vero (1) soltanto per l'elemento di riga 2 e colonna 2 della matrice (infatti e' l'unico elemento di a che e' uguale al corrispondente elemento di b). La selezione crea un vettore che ha soltanto gli elementi selezionati. Soltanto il numero 5 in questo caso. Soluzione 4 >> b(a>b|b>a) ans = 9 6 3 8 2 7 4 1 Questo esercizio e' simile al precedente. Vengono selezionati tutti gli elementi di b per cui e' vero che "a>b|b>a", cioe' che il numero di a sia maggiore di b OPPURE che il numero di b sia maggiore di a. Questo avviene per tutti i numeri che sono diversi, quindi tutti tranne l'elemento di riga 2 e colonna 2. Tutti gli elementi selezionati dalla relazione vengono copiati in un vettore. Soluzione 5 >> c=a;c(a>b)=b(a>b).^2 c = 1 2 3 4 5 16 9 4 1 7 8 Copio tutti i valori della matrice a in una nuova matrice c, dopodiche' assegno a tutti i valori di c selezionati dalla matrice logica a>b i quadrati dei corrispondenti valori di b. Ricordiamo che la matrice logica a>b ha valore 1 (vero) per gli elementi di a che sono maggiori di b e valore 0 (falso) negli altri casi. Il valore e' vero solo per gli elementi (2,3), (3,1), (3,2) e (3,3) della matrice, per cui solo questi elementi saranno cambiati nella matrice c. Soluzione 6 >> find(mod(a,b)) ans = 1 2 3 4 7 8 La funzione find restituisce gli indici dei valori non nulli passati come parametro della funzione. In questo caso il parametro e' mod(a,b) che equivale alla matrice dei resti delle divisioni tra gli elementi di a e di b. Il risultato finale e' l'indice degli elementi di ache non sono multipli di b (resto nullo). Soluzione 7 >> [r c]=find(mod(a,b)) r = 1 2 3 1 1 2 c = 1 1 1 2 3 3 Questo comando ha un effetto simile al comando precedente, ma anziche' restituire l'indice lineare (che varia da 1 a 9 e procede colonna per colonna) restituise le due coordinate corrispondenti ai valori non nulli. La prima coordinata e' il numero di riga, mentre la seconda coordinata e' il numero della colonna. Esercizio 7. (Vettori logici) Si scriva uno script che chieda l'inserimento di una sequenza di N numeri. Si stampino i valori dei numeri in posizione pari; Si stampino i valori dei numeri in posizione dispari; Si stampino i valori dei numeri pari; Si stampino i valori dei numeri dispari. Soluzione Codice clear all; 8 9 N=input('inserire N: '); for x=1:N a(x) = input('inserire numero: '); end % stampo soluzione punto 1 a(2:2:N) % stampo soluzione punto 2 a(1:2:N) % stampo soluzione punto 3 a(mod(a,2)==0) % stampo soluzione punto 4 a(mod(a,2)==1) Esecuzione inserire inserire inserire inserire inserire inserire ans = ans = ans = ans = N: 5 numero: numero: numero: numero: numero: 1 4 3 8 8 4 3 1 3 1 8 4 9 9 9 Esercizio 8. (Matrici rivisitate) Scrivere un programma in linguaggio MATLAB che, data una generica matrice A precedentemente acquisita costruisce una matrice P contenente solo le righe con indice pari della matrice A e una matrice D contenente solo le righe con indice dispari della matrice A. Soluzione Codice A=input('Inserire matrice: ') P=A(2:2:end,:) D=A(1:2:end,:) Esecuzione Inserire matrice: [0 9; 3 4; 6 4; 9 2; 0 0; 2 1] A = 0 9 3 4 9 6 4 9 2 0 0 2 1 3 4 9 2 2 1 0 9 6 4 0 0 10 P = Q = Esercizio 9. (I caffe' del dipartimento) In un dipartimento ci sono 10 persone, ognuna nell'ultima settimana ha consumato un certo numero di caffe' memorizzati in una matrice "caffe" data. 1. Si vuole sapere quanto deve pagare ogni persona sapendo che ogni caffe' ha un costo di 0,25 euro. 2. Si supponga che vi sia un costo fisso di noleggio della macchinetta per fare il caffe' pari a 10 euro a settimana. La meta' di tale costo e' divisa equamente tra i bevitori (coloro che hanno consumato almeno un caffe') e l'altra meta' tra i bevitori che ne hanno consumato di piu' rispetto alla media. Si dica quanto deve pagare ogni persona. Soluzione L'approccio che utilizziamo e' quello di creare un vettore logico che chiamiamo "bevitori" che seleziona coloro che hanno consumato almeno un caffe'. E un altro vettore logico che chiamiamo "superbevitori" che seleziona coloro che hanno consumato piu' caffe' rispetto alla media. Per le medie e le somme usiamo le funzioni aggregate mean e sum precedentemente introdotte. Codice caffe=[0 1 4 1 2 3 0 3 0 2 0 0 6 1 1 0 0 0 0 3 0 2 3 1 2 3 0 0 0 3 0 1 3 1 2 2 0 0 0 4 0 0 2 1 2 2 0 0 0 2 0 1 2 1 1 3 0 0 0 3 0; 1; 1; 1; 2; 1; 0; 0; 1; 3] ... ... ... ... ... ... ... ... ... % parte 1 somme_caffe = sum(caffe,2); 10 11 costi_a=somme_caffe*0.25 % parte 2 bevitori=somme_caffe~=0; costi_b=costi_a; costi_b(bevitori)=costi_b(bevitori)+5/sum(bevitori); superbevitori=somme_caffe>mean(somme_caffe); costi_b(superbevitori)=costi_b(superbevitori)+5/sum(superbevitori) Esecuzione costi_a = 0 1.5000 5.2500 1.7500 3.0000 3.5000 0 0.7500 0.2500 5.0000 costi_b = 0 2.1250 7.1250 2.3750 4.8750 5.3750 0 1.3750 0.8750 6.8750 Esercizio 10. (Gara automobilistica) Dopo una gara automobilistica si ha come risultato una tabella le cui colonne rappresentano gli N partecipanti (numerati da 1 a N) e le righe gli M giri di pista effettuati. Il valore di ogni generica cella (i,j) della tabella rappresenta il tempo impiegato dal partecipante j per percorrere il giro i. Supponendo che tale tabella sia stata importata in MATLAB come matrice A, si scrivano le istruzioni per: 1. calcolare il tempo totale medio che e' stato impiegato dai partecipanti per completare la gara; 2. determinare il vincitore della gara (cioè il numero del partecipante il cui tempo di percorrenza totale è minore di quello degli altri partecipanti); 3. tracciare un grafico in cui l'asse delle x rappresenta i giri compiuti dal vincitore e l'asse delle y il tempo necessario per percorrere i giri. A= [0.9 1.0 1.4 1.0 1.2 0.6 0.9 1.3 0.9 0.8 0.9 0.6 1.0 1.0 0.9 0.9 1.0 0.8 0.9 1.9 1.3 1.0 1.2 1.3 1.0 1.1 0.9 1.0 1.0 1.3 1.0 1.2 1.2 1.0 0.9 1.0 1.1 0.9 1.2 0.9 1.4 1.2 0.9 1.0 1.0 0.8 1.2 2.0 1.3 0.9 0.9 0.7 1.0 0.9 0.9; 1.1; 1.1; 1.2; 1.2; 1.1; 1.0; 1.0; 1.0; ... ... ... ... ... ... ... ... ... 11 12 1.2 1.3 3.2 1.4 1.2 0.9 1.3] Soluzione punto 1 tempomedio=mean(sum(A)) Soluzione punto 2 vincitore=find(sum(A)==min(sum(A)) Soluzione punto 3 [M N]=size(A); x=1:M; y=A(:,vincitore); plot(x,y) Esercizio 11. (Crivello di Eratostene) Si scriva uno script che trovi tutti i numeri primi compresi tra 2 e N utilizzando il metodo del Crivello di Eratostene. Secondo questo metodo bisogna scrivere tutti i numeri da 2 a N. Dopodiche' partendo da 2 fino ad arrivare a N si rimuovono dalla sequenza tutti i multipli del numero considerato, ad eccezione del numero considerato. Alla fine nella sequenza resteranno soltanto i numeri primi. Soluzione Codice N=input('Inserire N: '); % creo la sequenza a=2:N; % considero tutti i numeri da 2 a N-1: rimuovo i loro multipli for ii=2:N-1 multipli=mod(a,ii)==0; diversi=a~=ii; a(multipli & diversi) = []; end Soluzione alternativa Utilizzo un vettore di N elementi booleani. Ogni elemento vale true se e' presente nella sequenza, vale false se e' stato cancellato dalla sequenza. Prima di utilizzare il metodo del crivello tutti i numeri vengono inizializzati a true ad eccezione di 1 che non e' un numero primo per convenzione. Codice clear all; N=input('inserire N: '); a(2:N)=true; % assumo inizialmente che tutti i numeri siano primi a(1)=false; % 1 non e' un numero primo % marco come non primi i numeri multipli del numero iniziale for x=2:N a(2*x:x:N) = false; % il 2*x esclude il numero iniziale end % stampo risultato find(a) 12 13 Esecuzione inserire N: 30 ans = 2 3 5 7 11 13 17 19 23 29 Esercizio 12. (minore complementare) Data una matrice quadrata di dimensioni M x M e scelto un elemento in posizione (r, c), il suo minore complementare è dato dalla matrice che si ottiene eliminando la riga r e la colonna c dalla matrice di partenza. Ad esempio, data la seguente matrice: A=[0 0 0; " " " 0 1 2; " " " 3 4 5;]" " " " " Il minore complementare della cella in posizione <0, 1> contenente il valore 0 è dato dalla seguente matrice: A=[0 " " " 3 2; ... 5;]" Implementare la funzione che restituisce il minore di una matrice dati un numero di riga e di colonna Soluzione Codice function [minore]=minoreComplementare(m,i,j) minore = m; minore(i,:) = []; % eliminiamo la riga i-esima minore(:,j) = []; % eliminiamo la colonna j-esima 13