matlab/octave - esercitazione 5 - politecnico di...
TRANSCRIPT
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Facoltà di Ingegneria IndustrialeLaurea in Ingegneria Energetica, Meccanica e dei Trasporti
1
Matlab/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
!esercizi tratti da temi d’esame
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 1
3
MATLAB/Octave - Esercitazione 5
Si scriva una funzione Octave/MATLAB, di nome analisiMatrice, la quale, ricevendo come parametro una matrice a, verifica che i valori contenuti nella matrice non siano tutti uguali.
Se non sono tutti uguali:
-calcola il valore medio ma degli elementi di a (la somma di tutti gli elementi di a divisa per il loro numero);
-calcola e restituisce al chiamante il numero NM degli elementi di a maggiori di ma;
-calcola e restituisce al chiamante il numero Nm degli elementi di a minori di ma;
-calcola e restituisce al chiamante il valore medio mMag degli (NM) elementi di a maggiori di ma;
-calcola e restituisce al chiamante il valore medio mMin degli (Nm) elementi di a minori di ma;
-calcola e restituisce al chiamante il valoreval = NM*mMag-Nm*mMin.
Se invece i valori della matrice sono tutti uguali la funzione,
dopo aver fatto questa verifica, non calcola i valori sopra
indicati, ma si limita ad assegnare a tutti i parametri in uscita
il valore 0.
Informatica B - Esercitazione 12 del 14/01/2011
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 1 - Soluzione
4
Controllo che gli elementi della matrice non siano tutti uguali.
La funzione all(x) restituisce il valore logico 1 (true) se tutti gli elementi di x sono
diversi da zero, altrimenti restituisce o (falso).
Per matrici, all(X) opera lungo le colonne di X restituendo un vettore logico riga di 1 e
0.
MATLAB/Octave - Esercitazione 5
if (all(all(a == a(1,1)))) NM=0; Nm=0; mMag=0; mMin=0; val=0; returnend
function [NM Nm mMag mMin val] = analisiMatrice(a)
Definisco la funzione analisiMatrice.
In Matlab/Octave una funzione DEVE essere scritta in un file diverso dallo script
principale.
Il file in cui la funzione viene salvata DEVE avere lo stesso nome della funzione.
Nel nostro caso, il file in cui scriviamo la funzione analisiMatrice, verrà chiamato
analisiMatrice.m.
Informatica B - Esercitazione 12 del 14/01/2011
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 1 - Soluzione
5
MATLAB/Octave - Esercitazione 5
(a == a(1,1)) confronta tutta la matrice a con il suo primo elemento a(1,1) e
restituisce una matrice logica con 1 nelle posizioni in cui l’uguaglianza è verificata e 0
altrimenti.
(all(a == a(1,1))) verifica che tutti gli elementi della matrice logica appena restituita
siano pari ad 1. Restituisce un vettore logico di 1 e 0.
(all(all(a == a(1,1)))) verifica che tutti gli elementi del vettore logico siano 1.
Restituisce un solo valore logico 1 o 0.
Se tale valore è 1, vuol dire che tutti gli elementi di a sono uguali. In tal caso:
! le uscite di tutti gli analisiMatrice verranno poste uguali a 0NM=0; Nm=0; mMag=0; mMin=0; val=0;
! la funzione viene terminata
return
Informatica B - Esercitazione 12 del 14/01/2011
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 1 - Soluzione
6
MATLAB/Octave - Esercitazione 5
Nel caso in cui ci sia anche un solo elemento di a diverso da tutti gli altri, si calcolano i
valori richiesti dell’esercizio.
Informatica B - Esercitazione 12 del 14/01/2011
Calcolo il valore medio ma degli elementi di a.
Ottengo le dimensioni di a tramite la funzione size:
[R,C]=size(a);
Calcolo la media dei valori come somma di tutti i suoi valori diviso il numero di elementi:ma = sum(sum(a))/(R*C);
s = sum(x) calcola la somma dei valori contenuti nel vettore x.
Se x è una matrice, s sarà un vettore riga contenente la somma di ciascuna colonna di
a.
METODO ALTERNATIVO 1 - uso unico della funzione sum:
[R,C]=size(a);ma = sum(a(:))/(R*C);
METODO ALTERNATIVO 2 - non necessita delle dimensioni di a:
ma = mean(mean(a)); oppure ma = mean(a(:));
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 1 - Soluzione
7
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Calcolo il numero NM degli elementi di a maggiori di ma.
NM = sum(sum(a>ma));
(a>ma) produce una matrice logica con le stesse dimensioni di a. La matrice avrà 1
nelle posizioni in cui la disuguaglianza è verificata. 0 altrimenti.
sum(sum(a>ma)) sommando tutti gli 1 presenti nella matrice logica, otteniamo il
numero di elementi di a che hanno valore maggiore della sua media ma.
7 8 7 1 8 5
3 8 8 5 3 1
10 2 3 10 5 1
0 5 7 3 7 3
4 4 7 6 9 8
4 6 2 2 10 3
a
ma = 5
1 1 1 0 1 0
0 1 1 0 0 0
1 0 0 1 0 0
0 0 1 0 1 0
0 0 1 1 1 1
0 1 0 0 1 0
a>ma
2 3 4 2 4 1
sum(a>ma)
sum(sum(a>ma))
16
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 1 - Soluzione
8
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Analogamente calcolo il numero Nm degli elementi di a minori di ma.
Nm = sum(sum(a<ma));
Calcolo il valore medio mNag degli (NM) elementi di a maggiori di ma.
mMag = sum(a(a>ma))/NM;
Il procedimento è analogo al calcolo del numero di elementi maggiori di ma. Questa
volta, però, vogliamo estrarre anche il valore degli elementi.
7 8 7 1 8 5
3 8 8 5 3 1
10 2 3 10 5 1
0 5 7 3 7 3
4 4 7 6 9 8
4 6 2 2 10 3
a
1 1 1 0 1 0
0 1 1 0 0 0
1 0 0 1 0 0
0 0 1 0 1 0
0 0 1 1 1 1
0 1 0 0 1 0
a>ma sum(a((a>ma))/NM
7,87507 10 8 ... 9 10 8
a(a>ma)
Con l’istruzione a(a>ma) individuiamo solo
gli elementi di a che sono in corrispondenza
degli 1 della matrice logica . Quello che viene
restituito non è più una matrice ma un
vettore. Nel calcolo della somma, quindi, non
occorre più usare due funzioni sum annidate,
ne basterà una.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 1 - Soluzione
9
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Analogamente calcolo mMin.
mMin = sum(a(a<ma));
Calcolo il valore di val.
val = NM*mMag-Nm*mMin;
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 1 - Soluzione
10
Esercizio 1 - Codice completo
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
% Tema del 25/01/2010 - Esercizio 1
function [NM Nm mMag mMin val] = analisiMatrice(a) if (all(all(a == a(1,1)))) NM=0; Nm=0; mMag=0; mMin=0; val=0; returnend [R,C]=size(a);ma = sum(sum(a))/(R*C);NM = sum(sum(a>ma));Nm = sum(sum(a<ma));mMag = sum(a(a>ma))/NM;mMin = sum(a(a<ma))/Nm;val = NM*mMag-Nm*mMin;
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2
11
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Un call centre possiede un archivio che contiene informazioni sulla
produttività dei dipendenti. L’archivio consiste in un file di testo
(prod.dat) contenente una tabella di 3 colonne:-nella prima sono contenuti i nomi dei dipendenti,-nella seconda la media di ore giornaliere di lavoro relative all’ultimo mese
-nella terza il numero di contratti stipulati in quel mese dal dipendente.
L’azienda calcola la retribuzione dei dipendenti nel seguente modo:
se un dipendente ha lavorato in media meno di 7 ore al giorno la
paga è di 5! all’ora, se ha lavorato da 7 a 12 ore in media, è di
10!, altrimenti è di 6!.
Ai fini del calcolo dello stipendio si supponga che i giorni di
lavoro al mese siano 24. Inoltre se il numero di contratti stipulati
è superiore a 48 l’azienda premia un dipendente con un bonus di
500!.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2
12
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Si scriva uno script che legga da file l’archivio sulla produttività
(utilizzando la funzione predefinita textread) e inserisca i dati letti in un array di strutture.
Tale array deve contenere, per ogni dipendente, una struttura con un
campo nome per memorizzare il nome del dipendente, un campo ore per
il numero medio di ore, e un campo contratti per il numero di contratti.
Successivamente lo script deve
-calcolare, per ogni dipendente, lo stipendio, memorizzandolo in un opportuno campo di nome stipendio aggiunto alla struttura che già
contiene gli altri dati,
-stampare a video il numero dei dipendenti che, pur lavorando più di 12 ore al giorno (in media), guadagnano meno della media dei
dipendenti.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2 - Soluzione
13
MATLAB/Octave - Esercitazione 5
Leggo i dati dall’archivio prod.dat e li memorizzo nella struttura richiesta.
Informatica B - Esercitazione 12 del 14/01/2011
[nomi ore contratti] = textread('prod.dat', '%s %f %f'); for i=1:length(nomi) dipendenti(i).nome = nomi(i); dipendenti(i).ore = ore(i); dipendenti(i).contratti = contratti(i);end
La funzione [A,B,C,...]=textread(‘filename’, ‘format’) legge i dati da
filename e li pone nelle variabili A, B, C, etc. Il tipo di dato di ciascun elemento restituito
è dato dalla stringa format. Il numero degli argomenti restituiti deve essere uguale al
numero di conversioni specificate da format.
textread confronta e converte gruppi di caratteri letti da filename. Ogni campo di
input è costituito da una stringa di caratteri consecutivi spazio bianco escluso.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2 - Soluzione
14
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Le variabili [nomi ore contratti] sono tre vettori.
Per calcolare la dimensione di qualsiasi tipo di dato si può usare la funzione
[r c] = size(x) che restituisce il numero r di righe ed il numero c di colonne
dell’array x.
Per i vettori si preferisce utilizzare la funzione length(x) che restituisce direttamente la
dimensione del vettore diversa da 1, quindi, la sua lunghezza.
dipendenti dipendenti(1) nome
ore
contratti
dipendenti(length(nomi))
nome
ore
contratti
Struttura dipendenti
dipendenti(2)
dipendenti(...)
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2 - Soluzione
15
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Per ogni dipendente calcolo la sue retribuzione in base al numero di ore lavorative ed in
base al numero di contratti stipulati.
for i=1:length(nomi) coefficiente = 10; if dipendenti(i).ore < 7 coefficiente = 5; elseif dipendenti(i).ore > 12 coefficiente = 6; end dipendenti(i).stipendio = dipendenti(i).ore * 24 * coefficiente; if dipendenti(i).contratti >= 48 dipendenti(i).stipendio = dipendenti(i).stipendio + 500; endend
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2 - Soluzione
16
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Per ogni dipendente:for i=1:length(nomi)
inizializzo il coefficiente di retribuzione a 10! coefficiente = 10;
se il dipendente ha lavorato meno di 7 ore, il coefficiente sarà 5! if dipendenti(i).ore < 7 coefficiente = 5;
altrimenti, se il dipendente ha lavorato più di 12 ore, il coefficiente sarà 6! elseif dipendenti(i).ore > 12 coefficiente = 6; end
Calcolo lo stipendio di ogni dipendente in base alle ore lavorative e al coefficiente stimato dipendenti(i).stipendio = dipendenti(i).ore * 24 * coefficiente;
In Matlab/Octave è possibile aggiungere nuovi campi ad una struttura già esistente man
mano che sono necessari. Non è assolutamente obbligatorio farlo al momento della
prima compilazione della struttura. Quando al campo stipendio di un dipendente
viene assegnato un valore, viene creato un campo stipendio per tutti gli altri
dipendenti inizializzato con l’insieme vuoto [].
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2 - Soluzione
17
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Se il numero di contratti stipulati dal dipendente sono maggiori o uguali a 48, aggiungo il
bonus al suo stipendio if dipendenti(i).contratti >= 48 dipendenti(i).stipendio = dipendenti(i).stipendio + 500; end
chiudo il ciclo forend
mediastipendi = mean([dipendenti.stipendio]);numdipendenti = sum([dipendenti.stipendio] < mediastipendi &... [dipendenti.ore]> 12);
Calcolo lo stipendio medio di tutti i dipendenti dell’azienda ed il numero di dipendenti
lavorano più di 12 ore al giorno e guadagnano meno della media dei dipendenti.
Le due relazioni logiche [dipendenti.stipendio] < mediastipendi e
[dipendenti.ore]> 12 restituiscono due vettori logici della stessa lunghezza.
La lunghezza è pari al numero di dipendenti presenti nella struttura.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2 - Soluzione
18
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
[dipendenti.stipendio] =
[dipendenti.stipendio] < mediastipendi
[dipendenti.ore] =
[dipendenti.ore]> 12
[dipendenti.stipendio] < mediastipendi & [dipendenti.ore]> 12
700 800 1.000 ... 2.000 500 550
mediastipendi = 800
1 0 0 ... 0 1 1
Esempio:
12 13 15 ... 20 13 13
0 1 1 ... 1 1 1
1 0 0 ... 0 1 1 0 1 1 ... 1 1 1
0 0 0 ... 0 1 1
&
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2 - Soluzione
19
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Sommando gli elementi presenti nel vettore logico risultante avremo il numero di
dipendenti che soddisfano contemporaneamente le due relazioni.
numdipendenti = sum([dipendenti.stipendio] < mediastipendi &... [dipendenti.ore]> 12);
Stampo a video il risultato:fprintf('Numero dipendenti richiesti: %d \n', numdipendenti);
METODO ALTERNATIVO - uso la funzione disp:
disp(['Numero dipendenti richiesti:' num2str(numdipendenti]))
Per visualizzare più di un elemento con la funzione disp è obbligatorio usare le
parentesi quadre: [elemento1 elemento2 elemento3]Per visualizzare variabili non contenenti stringhe è obbligatorio utilizzare la funzione
num2str(variabile).
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 2 - Soluzione
20
Esercizio 2 - Codice completo
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
% Tema del 25/01/2010 - Esercizio 2
[nomi ore contratti] = textread('prod.dat', '%s %f %f'); for i=1:length(nomi) dipendenti(i).nome = nomi(i); dipendenti(i).ore = ore(i); dipendenti(i).contratti = contratti(i);end for i=1:length(nomi) coefficiente = 10; if dipendenti(i).ore < 7 coefficiente = 5; elseif dipendenti(i).ore > 12 coefficiente = 6; end dipendenti(i).stipendio = dipendenti(i).ore * 24 * coefficiente; if dipendenti(i).contratti >= 48 dipendenti(i).stipendio = dipendenti(i).stipendio + 500; endend mediastipendi = mean([dipendenti.stipendio]);numdipendenti = sum([dipendenti.stipendio] < mediastipendi & [dipendenti.ore]> 12); fprintf('Numero dipendenti richiesti: %d \n', numdipendenti);
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 3
21
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Si dice che un vettore riga A è un maxHeap se, per ogni indice i di A, valgono le seguenti due relazioni:
A(i)>A(2*i) e A(i)>A(2*i+1) (NB: le due relazioni devono essere verificate solo se i valori di i, 2*i e 2*i+1 sono indici validi per l'array).
Si consideri, ad esempio, il vettore X=[8 4 6 1 2 5]. Verifichiamo
se è un maxHeap. X(1), cioè 8, è maggiore sia di X(2*1) sia di X(2*1+1). Analogamente X(2) è maggiore di X(2*2) e X(2*2+1). Il valore 2*3+1 non è un indice valido per il vettore per cui, X(3) va confrontato solo con X(2*3). Poiché X(3) è maggiore di di X(6) e
non ci sono altri elementi i per cui 2*i e 2*i+1 sono indici validi di X, possiamo concludere che X è un maxHeap.
Scrivere una funzione ricorsiva che, preso come parametro un
vettore A, restituisce 1 se A è un maxHeap, 0 altrimenti. Si suggerisce di sviluppare una funzione con la seguente testata:
function r = maxHeap(A,i) dove A è il vettore e i la posizione dell’elemento da controllare. Si intende che, per controllare per
esempio che il vettore V sia un maxHeap (assegnando il risultato alla variabile m), si debba eseguire la chiamata m = maxHeap(V,1).
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 3 - Soluzione
22
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Essendo un problema di tipo ricorsivo, va analizzato cercando di distinguere i casi basi
dai passi induttivi.
CASO BASE 1: l’array A è lungo meno di 2*i.
In questo caso non ci sono indici validi per verificare se A(i)>A(2*i) e A(i)>A(2*i
+1), quindi, seguendo le istruzioni riportate nell’esempio, possiamo dire che A è
maxHeap.
CASO BASE 2: l’array A è lungo meno di 2*i+1.
Gli unici indici validi da verificare sono i e 2*i, ovvero la relazione A(i)>A(2*i).
PASSO INDUTTIVO: nessuno dei due casi precedenti è verificato.
Per definire A come MaxHeap, le relazioni A(i)>A(2*i) e A(i)>A(2*i+1) devono
essere verificate per tutti gli indici validi dell’array.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 3 - Soluzione
23
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Dichiaro la funzionefunction r = maxHeap(A,i)
Caso base n°1, la lunghezza dell’array è inferiore a 2*iif length(A) < 2*i r = 1;
Caso base n°2, la lunghezza dell’array è inferiore a 2*i+1elseif length(A) < 2*i+1
L’unico indice valido per il confronto è 2*i r = A(i) > A(2*i);else
Passo induttivo, posso confrontare l’elemento in posizione i-esima con quelli
rispettivamente nelle posizioni 2*i e 2*i+1. r = A(i) > A(2*i) && A(i) > A(2*i + 1) && maxHeap(A, i+1);end
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 3 - Soluzione
24
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
ed analizziamo in maniera più approfondita il passo induttivo:r = A(i) > A(2*i) && A(i) > A(2*i + 1) && maxHeap(A, i+1);
Affinché un vettore sia MaxHeap, le due relazioni
A(i) > A(2*i) e A(i) > A(2*i + 1)
devono essere verificate per tutti gli indici validi del vettore stesso.
Se nel codice siamo arrivati a calcolare il passo induttivo, vuol dire che abbiamo
verificato l’esistenza degli indici validi per il confronto (casi base).
Con la chiamata maxHeap(A, 1), nel passo induttivo si controlla che le condizioni
per cui:
-A(1) > A(2)-A(1) > A(3)-la porzione di vettore da A(2)=4 in poi sia MaxHeap
siano verificate contemporaneamente.
8 4 6 1 2 5X =
Consideriamo il vettore
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 3 - Soluzione
25
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Ognuna delle tre relazioni, essendo relazioni logiche, restituisce 1 se verificata e 0
altrimenti.
Ponendo r uguale all’ and delle tre relazioni, siamo sicuri che assumerà il valore 1
solamente quando tutte e tre sono verificate nello stesso momento.
In questo caso, tutto il vettore è maxHeap.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 3 - Soluzione
26
Esercizio 3 - Codice completo
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
% Tema del 25/01/2010 - Esercizio 3
function r = maxHeap(A,i) if length(A) < 2*i r = 1;elseif length(A) < 2*i+1 disp(['analizzo elemento numero: ' num2str(i)]); disp(['lo confronto con elemento numero: ' num2str(2*i)]); r = A(i) > A(2*i);else disp(['analizzo elemento numero: ' num2str(i)]); disp(['lo confronto con elemento numero: ' num2str(2*i) ' e ' num2str(2*i+1)]); r = A(i) > A(2*i) && A(i) > A(2*i + 1) && maxHeap(A, i+1);end
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4
27
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Si consideri la rappresentazione di un punto nel piano come una
struttura con due campi x e y, rispettivamente ascissa e ordinata del punto. Una linea spezzata nel piano sarà quindi
rappresentabile come l’insieme dei suoi vertici, per esempio
tramite un vettore di punti.
1.Scrivere una funzione in Matlab che, data la rappresentazione di
una spezzata come precedentemente illustrato, restituisca un
valore logico che vale 1 se e solo se le ascisse dei punti che la compongono sono strettamente crescenti.
2.Scrivere una funzione in Matlab che, data la rappresentazione di
una spezzata come precedentemente illustrato, restituisca la
lunghezza della spezzata, ossia la lunghezza totale dei segmenti
che la compongono.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione 28
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
3.Scrivere uno script che legga da un file di testo spez.txt una sequenza di punti rappresentanti una spezzata. Il file è
strutturato in modo che ogni riga contenga prima l’ascissa poi
l’ordinata di uno stesso punto, separati da uno spazio. Lo script,
leggendo i dati dal file, deve riempire un vettore, di nome
spezzata, contenente strutture che rappresentano i punti della
spezzata nel modo sopra indicato.
Lo script poi:
a.Verifica che spezzata sia composta
da punti con ascisse strettamente
crescenti e che spezzata abbia una e
una sola intersezione con l’asse delle
ascisse (l’intersezione può essere sia
un vertice della spezzata, sia parte
di un segmento che la compone);
La figura mostra un esempio di
spezzata che rispetta queste
condizioni.
Esercizio 4
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione 29
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
b.Qualora la condizione al punto a) sia verificata, lo script deve
produrre, a partire dalla spezzata di partenza, due vettori
distinti, sp1 ed sp2, tali per cui sp1 contenga i vertici di spezzata con ordinate non negative (positive o eventualmente
nulle), e sp2 contenga i vertici di spezzata con ordinate negative. Infine, lo script calcola la differenza tra la lunghezza
di sp1 e la lunghezza di sp2 (la lunghezza di una spezzata è definita come al punto 2). Nel caso della figura qui sopra, sp1 corrisponde alla spezzata composta dai primi tre punti, sp2 dai restanti 3 punti.
Esercizio 4
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
30
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Risolviamo l’esercizio procedendo per punti.
1.Scrivere una funzione in Matlab che, data la rappresentazione di
una spezzata come precedentemente illustrato, restituisca un valore
logico che vale 1 se e solo se le ascisse dei punti che la compongono sono strettamente crescenti.
Definisco la funzione in modo che prenda in ingresso la struttura contenente i dati della
spezzata e restituisca in output una variabile flag, inizializzata ad 1, che indica se le
ascisse della spezzata sono in sequenza crescente.
function ris = tuttoCrescente(spezzata) ris = 1;
Il passo successivo è controllare tutte le coppie consecutive di ascisse e verificare che il
i loro valori siano crescenti. Nel caso in cui questa relazione non sia verificata anche per
una sola coppia di valori, il controllo si interrompe e la funzione restituisce 0.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
31
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
for j=1:length(spezzata)-1 if spezzata(j).x >= spezzata(j +1).x ris = 0; return; endend
Il comando return comporta l’interruzione della funzione corrente ed il ritorno
all’esecuzione della funzione chiamante.
2.Scrivere una funzione in Matlab che, data la rappresentazione di
una spezzata come precedentemente illustrato, restituisca la
lunghezza della spezzata, ossia la lunghezza totale dei segmenti
che la compongono.
La distanza tra due punti (x1, y1), (x2, y2) è data da:
l =!
(x1 ! x2)2 + (y1 ! y2)2
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
32
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
for jj=1:length(spezzata)-1 l = l + sqrt((spezzata(jj + 1).x - spezzata(jj).x) ^ 2 +... (spezzata(jj + 1).y - spezzata(jj).y)^ 2);end
Definisco la funzione ed inizializzo la lunghezza della spezzata a 0.
function l = lunghezza(spezzata) l = 0;
Per ogni coppia di punti della spezzata applico la formula della distanza sommando le
lunghezze dei singoli segmenti che la compongono in maniera incrementale.
Somma incrementale.l = l + ...
Aggiorno il valore già
presente nella variabile
l con il nuovo.
l =!
(x1 ! x2)2 + (y1 ! y2)2
l =!
(x1 ! x2)2 + (y1 ! y2)2 +!
(x2 ! x3)2 + (y2 ! y3)2
l =!
(x1 ! x2)2 + (y1 ! y2)2+!
(x2 ! x3)2 + (y2 ! y3)2+...+!
(xn!1 ! xn)2 + (yn!1 ! yn)2
1
l =!
(x1 ! x2)2 + (y1 ! y2)2
l =!
(x1 ! x2)2 + (y1 ! y2)2 +!
(x2 ! x3)2 + (y2 ! y3)2
l =!
(x1 ! x2)2 + (y1 ! y2)2+!
(x2 ! x3)2 + (y2 ! y3)2+...+!
(xn!1 ! xn)2 + (yn!1 ! yn)2
1
l =!
(x1 ! x2)2 + (y1 ! y2)2
l =!
(x1 ! x2)2 + (y1 ! y2)2 +!
(x2 ! x3)2 + (y2 ! y3)2
l =!
(x1 ! x2)2 + (y1 ! y2)2+!
(x2 ! x3)2 + (y2 ! y3)2+...+!
(xn!1 ! xn)2 + (yn!1 ! yn)2
1
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
33
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Leggo i dati dal file con la funzione textread considerando che il file di testo ha la
seguente struttura:
3.Scrivere uno script che legga da un file di testo spez.txt una sequenza di punti rappresentanti una spezzata. Il file è strutturato
in modo che ogni riga contenga prima l’ascissa poi l’ordinata di uno
stesso punto, separati da uno spazio. Lo script, leggendo i dati dal
file, deve riempire un vettore, di nome spezzata, contenente
strutture che rappresentano i punti della spezzata nel modo sopra
indicato.
x1
x2
x3
...
xn
y1
y2
y3
...
yn
La funzione
[ascisse ordinate]=textread(‘filename’, ‘format’) confronta e converte gruppi di
caratteri letti da filename. Ogni campo di input è costituito da una stringa di caratteri consecutivi
spazio bianco escluso.
textread legge tutti i caratteri, fino al primo spazio bianco, e li pone in ascisse(1). Tutti i caratteri compresi tra il primo ed il successivo spazio bianco
verranno posti in ordinate(1). Se al posto di uno spazio bianco, la funzione
incontra un delimitatore di linea(), il successivo gruppo di caratteri tornerà al far parte di
della prima variabile in uscita, per la precisione sarà ascisse(2).
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
34
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
[ascisse ordinate]=textread('spez.txt', '%d %d');
for jj=1:length(ascisse) spezzata(jj).x = ascisse(jj); spezzata(jj).y = ordinate(jj);end
Lo script poi:
a.Verifica che spezzata sia composta da punti con ascisse
strettamente crescenti e che spezzata abbia una e una sola
intersezione con l’asse delle ascisse (l’intersezione può essere
sia un vertice della spezzata, sia parte di un segmento che la
compone);
b.Qualora la condizione al punto a) sia verificata, lo script deve
produrre, a partire dalla spezzata di partenza, due vettori
distinti, sp1 ed sp2, tali per cui sp1 contenga i vertici di spezzata con ordinate non negative (positive o eventualmente
nulle), e sp2 contenga i vertici di spezzata con ordinate negative. Infine, lo script calcola la differenza tra la lunghezza
di sp1 e la lunghezza di sp2 (la lunghezza di una spezzata è definita come al punto 2). Nel caso della figura qui sopra, sp1 corrisponde alla spezzata composta dai primi tre punti, sp2 dai restanti 3 punti.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
35
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Struttura della soluzione:
controllo che la spezzata sia non decrescente
se la spezzata è non decrescente
controllo il numero di intersezioni con l’asse delle ascissesiamo in presenza di una intersezione quando due ordinate consecutive hanno segno opposto o l’ordinata corrente
ha valore pari a zero
se ho una sola intersezione
divido le ordinate tra positive e negative
calcolo la differenza di lunghezza delle due curve
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
36
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
% controllo che la spezzata sia non decrescentecrescente = tuttoCrescente(spezzata);if (crescente) intersezioni = 0; % controllo il numero di intersezioni con l’asse delle ascisse for jj=1:length(spezzata)-1 % siamo in presenza di una intersezione quando due ordinate % consecutive hanno segno opposto o l’ordinata corrente ha valore % pari a zero if (spezzata(jj).y * spezzata(jj+1).y < 0 || spezzata(jj).y == 0) intersezioni=intersezioni+1; end end if (spezzata(end).y==0) intersezioni=intersezioni+1; end % se ho una sola intersezione if (intersezioni == 1) % divido le ordinate tra positive e negative sp1 = spezzata([spezzata.y]>=0); sp2 = spezzata([spezzata.y]<0); % calcolo la differenza di lunghezza delle due curve differenza = lunghezza(sp1) - lunghezza(sp2); endend
Nel precedente ciclo for controlliamo se il valore di tutte le ordinate della spezzata sono uguali a zero, tranne l’ultima. Con questo costrutto if estendiamo il controllo anche all’ordinata dell’ultimo punto.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
37
Esercizio 4 - Codice completo
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
% Tema del 08/02/2010 - Esercizio 1 [ascisse ordinate]=textread('spez.txt', '%d %d'); plot(ascisse, ordinate, 'o')hold onplot(ascisse, ordinate) for jj=1:length(ascisse) spezzata(jj).x = ascisse(jj); spezzata(jj).y = ordinate(jj);end
crescente = tuttoCrescente(spezzata);
if (crescente) intersezioni = 0; for jj=1:length(spezzata)-1 if (spezzata(jj).y * spezzata(jj+1).y < 0 || spezzata(jj).y == 0) intersezioni=intersezioni+1; end end if (spezzata(end).y==0) intersezioni=intersezioni+1; end if (intersezioni == 1) sp1 = spezzata([spezzata.y]>=0); sp2 = spezzata([spezzata.y]<0); differenza = lunghezza(sp1) - lunghezza(sp2); endend
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 4 - Soluzione
38
Esercizio 4 - Codice completo
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
function ris = tuttoCrescente(spezzata) ris = 1;for jj=1:length(spezzata)-1 if spezzata(jj).x >= spezzata(jj +1).x ris = 0; return; endend
function l = lunghezza(spezzata) l = 0;for jj=1:length(spezzata)-1 l = l + sqrt((spezzata(jj + 1).x - spezzata(jj).x) ^ 2 + (spezzata(jj + 1).y - spezzata(jj).y)^ 2);end
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 5
39
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Si consideri la seguente funzione MATLAB ricorsiva, che si intende
applicata a numeri naturali (interi non negativi):
function [ris] = qd(n) if (0<=n && n<10) ris = n==0 || n==9;else r = mod(n, 10); ris = qd(floor(n/10) + r);end
1. Si mostri l'effetto delle due chiamate qd(135) e qd(142) disegnando gli ambienti locali delle successive chiamate ricorsive.
2. Si indichi qual’è la funzione matematica calcolata da qd, giustificando la risposta.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 5 - Soluzione
40
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Analizzo il codice della funzione.
function ris = qd(n) if (0<=n && n<10) ris = n==0 || n==9;else r = mod(n, 10); ris = qd(floor(n/10) + r);end
Dichiarazione
se il valore passato alla funzione è compreso tra 0 e 10
(escluso), il risultato sarà ris = 1 se n=0 o se n=9
pongo in r il resto della divisione tra n/10richiamo la funzione con il nuovo valore:
floor(n/10) + r
altrimenti
La funzione mod(x,y) è il risultato di x-n.*y dove n=floor(x./y) se y ~= 0.In breve possiamo dire che restituisce il resto della divisione tra x ed y.
La funzione floor(x) arrotonda x all’intero più vicino per difetto.
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 5 - Soluzione
41
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Chiamata 1)
n = 135 non è compreso tra 0 e 10
r = 5 135/10=13.5 ovvero 13 con resto 5
ris = qd(13 + 5)
Chiamata 2)
n = 18 non è compreso tra 0 e 10
r = 8 18/10=1.8 ovvero 1 con resto 8
ris = qd(1 + 8)
Chiamata 3)
n = 9 è compreso tra 0 e 10 ed è uguale a 9
ris = 1
qd(135)
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 5 - Soluzione
42
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Stack
Salvo Daniele Valente
Dipartimento di Elettronica e Informazione
Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione
Esercizio 5 - Soluzione
43
MATLAB/Octave - Esercitazione 5
Informatica B - Esercitazione 12 del 14/01/2011
Chiamata 1)
n = 142 non è compreso tra 0 e 10
r = 5 142/10=14.2 ovvero 14 con resto 2
ris = qd(14 + 2)
Chiamata 2)
n = 16 non è compreso tra 0 e 10
r = 6 16/10=1.6 ovvero 1 con resto 6
ris = qd(1 + 6)
Chiamata 3)
n = 7 è compreso tra 0 e 10 ma diverso sia da 9 che da 0
ris = 0
qd(142)
La funzione qd calcola la somma modulo 10 delle cifre del suo argomento e verifica se è
nulla, quindi stabilisce se il suo argomento è un numero divisibile per 9.