Esercizi(di(MATLAB per$il$corso$di$InformaticaB/C 2014/2015 · Corsodi%Informatica%B/C2014515% 151%...

63
Corso di Informatica B/C 201415 11 Esercizi di MATLAB per il corso di Informatica B/C 2014/2015 Chapter 1 Introduzione .............................................................................................................................12 Chapter 2 Funzioni ..................................................................................................................................220 Chapter 3 Ricorsione ...............................................................................................................................342 Chapter 4 Accesso ai file..........................................................................................................................462 Chapter 5 Diagrammi ..............................................................................................................................563

Transcript of Esercizi(di(MATLAB per$il$corso$di$InformaticaB/C 2014/2015 · Corsodi%Informatica%B/C2014515% 151%...

Corso  di  Informatica  B/C  2014-­‐15   1-­‐1  

Esercizi  di  MATLAB  per  il  corso  di  Informatica  B/C  

2014/2015      

Chapter  1  Introduzione  .............................................................................................................................  1-­‐2  

Chapter  2  Funzioni  ..................................................................................................................................  2-­‐20  

Chapter  3  Ricorsione  ...............................................................................................................................  3-­‐42  

Chapter  4  Accesso  ai  file  ..........................................................................................................................  4-­‐62  

Chapter  5  Diagrammi  ..............................................................................................................................  5-­‐63  

 

   

Corso  di  Informatica  B/C  2014-­‐15   1-­‐2  

Chapter  1 Introduzione    

1. Scrivere  un  programma  che  data  una  matrice  a  NxN  crea  una  nuova  matrice  b  ruotata  di  90  gradi  in  senso  antiorario  rispetto  ad  a.  Si  consideri  N=4  e  la  matrice  a  inizializzata  con  i  valori    

[1  2  3  4;    2  3  4  5;    6  7  8  9;    0  0  0  0]    

Soluzione  -­‐  script  

N=4; a = [1 2 3 4; 2 3 4 5; 6 7 8 9; 0 0 0 0]; for x=1:N for y=1:N b(N+1-y,x)=a(x,y); end end %stampo la matrice originale a %stampo la matrice ruotata b  

Soluzione  -­‐  script  

N=4; a=[1 2 3 4; 2 3 4 5; 6 7 8 9; 0 0 0 0]; %utilizzo la funzione di MATLAB rot90 a b=rot90(a)  

   

Corso  di  Informatica  B/C  2014-­‐15   1-­‐3  

2. Si  realizzi  uno  script  in  Matlab  che  richieda  l’inserimento  dei  tre  coefficienti  di  un’equazione  di  secondo  grado:    

e  stampi  il  valore  delle  radici  reali.    

  Suggerimento    

Le  radici  di  un’equazione  di  secondo  grado  possono  essere  calcolate  mediante  la  seguente  formula:  

 

Soluzione  -­‐  script  

% Per risolvere l'esercizio bisogna calcolare il discriminante %dell'equazione con la formula b^2-4*a*c Se è positive abbiamo due %radici distinte, %Se è nullo le radici sono reali e coincidenti, %Se è negative le radici non sono reali. a = input('Inserire a: '); b = input('Inserire b: '); c = input('Inserire c: '); delta = b^2-4*a*c; if delta < 0 disp('L''equazione non ha soluzioni reali'); elseif delta==0 disp(['x=' num2str(-b/(2*a))]); else disp(['x1=' num2str((-b-sqrt(delta))/(2*a)) ' x2=' ... num2str((-b+sqrt(delta))/(2*a))]); end  

   

ax

2 + bx+ c = 0

r =�b±

pb2 � 4ac

2

Corso  di  Informatica  B/C  2014-­‐15   1-­‐4  

3. Realizzare  uno  script  che,  data  una  matrice  quadrata,    

a. ne  estragga  la  diagonale  principale.  b. ne  estragga  la  diagonale  secondaria.    

c. elimini  la  diagonale  principale  e  la  secondaria  

Soluzione  

a)  

-­‐primo  modo  usare  la  matrice  logica  con  true  sulla  diagonale  principale;  possiamo  costruire  una  matrice  logica   B = logical(eye(N))   dove   N   è   la   dimensione   della   matrice   di   cui   vogliamo   estrarre   la  diagonale    

A(logical(eye(N))) -­‐secondo  modo  utilizzando  la  funzione  diag  :)    

diag(A)  

b)  

-­‐primo  metodo,  utilizzando  logical  e  rot90    

A(logical(rot90(eye(N))))  

-­‐secondo  metodo,  utilizzando  diag  e  rot90    

diag(rot90(A))  

c)  

-­‐primo  metodo,  usando  logical  e  eye  

A(logical(eye(N))) = 0 % elimino la diagonale principale A(logical(rot90(eye(N)))) = 0 % elimino la diagonale secondaria  

-­‐  secondo  metodo  usando  diag  

A  -­‐  diag(diag(A))                                                          %elimino  la  diagonale  principale  A  -­‐  fliplr(diag(diag(rot90(A))))            %elimino  la  diagonale  secondaria    

   

Corso  di  Informatica  B/C  2014-­‐15   1-­‐5  

4. Scrivere   uno   script   che   chieda   un   anno   all’utente   e   stampi   a   video   se   l’anno   è   bisestile.   Il  programma  deve   continuare  a   chiedere  all’utente  anni,   finché  gli   anni   inseriti   sono  bisestili.  Stampare  a  video  il  numero  totale  di  anni  bisestili  inseriti.  

Soluzione  

bisestili.m  -­‐  script  

clear    clc    bisestile  =  1;  counter  =  0;    while(bisestile)    

n  =  input(['inserire  anno  ']);    div_4  =  (mod(n  ,  4)  ==  0);    div_100  =  (mod(n  ,  100)  ==  0);    div_400  =  (mod(n  ,  400)  ==  0);    bisestile  =  ((div_4)  &&  ~(div_100))  ||  (div_400);    stringa_output  =  num2str(n);    if(bisestile  ==  0)  

stringa_output  =  [stringa_output  ,  '  NON  e''  '];    else  

stringa_output  =  [stringa_output  ,'  e''  '];    counter  =  counter  +  1;    

end    stringa_output  =  [stringa_output  ,  'bisestile'];    disp(stringa_output);    

end    disp(['game  over  hai  inserito  esattamente  '  ,  num2str(counter)  ,  '  bisestili'])          

Corso  di  Informatica  B/C  2014-­‐15   1-­‐6  

5. Scrivere  uno  script  che  analizzi  i  voti  del  primo  compitino  degli  anni  precedenti,  stampando  a  schermo:    

• media  dei  voti  • la  media  dei  voti  sufficienti  • la  varianza  dei  voti  sufficienti  • il  numero  di  promossi  al  primo  compitino    

%  A.A.  2012-­‐-­‐2013    voti  =  [2  8  4  8.1  9.25  11.25  4.75  17  6.25  13  10  2  3.25  3.75...    8.5  16  8  1  2.5  12  10.75  6  12  10  11.75  3.5  10.5  8.5  14.25...    16.5  10.75  8  12  1  10  13  6.75  5.75  9.5  12.75  11  8.5  10.25...    14.5  4.25  5.5  9.75  16.5  13  15  13  13.75  13.5];          

Soluzione  

media.m  -­‐  script  

clear  clc  %  A.A.  2012-­‐-­‐2013  voti=[2  8  4  8.1  9.25  11.25  4.75  17  6.25  13  10  2  3.25  3.75  8.5  16  8  1  2.5  12  10.75  6  12  10  11.75  3.5  10.5  8.5  14.25  16.5  10.75  8  12  1  10  13  6.75  5.75  9.5  12.75  11  8.5  10.25  14.5  4.25  5.5  9.75  16.5  13  15  13  13.75  13.5];      %  calcolo  media:  soluzione  "alla  C"    count  =  0;    tot  =0;    for  ii  =  voti    

tot=tot  +  ii;    count  =  count  +  1;    

end  media  =  tot/count;  %  oppure  %  soluzione  alla  MATLAB  media  =  mean(voti);  disp(['media:  '  ,  num2str(media)]);    %  calcolo  media  sufficienti:  soluzione  "alla  C"    count  =  0;    tot  =  0;    for    ii  =  voti(voti  >=  8)    

tot=tot  +  ii;    count  =  count  +  1;    

end  media_suff  =  tot/count;    

Corso  di  Informatica  B/C  2014-­‐15   1-­‐7  

 %  oppure    %  soluzione  alla  MATLAB    media_suff  =  mean(voti(voti  >=  8))    disp(['media  dei  sufficienti:  '  ,  num2str(media_suff)]);        %  calcolo  della  varianza  dei  voti  sufficienti  "alla  C"    count  =  0;    tot  =  0;    for  ii  =  voti(voti  >=  8)    

tot  =  tot  +  (ii  -­‐  media_suff).^2;    count  =  count  +  1;    

end    var_suff  =  tot/count;      %  oppure  soluzione  alla  MATLAB    var_suff  =  var(voti(voti  >=  8))    disp(['varianza  dei  sufficienti:  '  ,  num2str(var_suff)]);      %  numero  di  voti  sufficienti:  soluzione  "alla  C"    n_suff  =  0;    for  ii  =  (voti  >=  18)    

n_suff  =  n_suff  +  ii  ;      end        %  oppure    %  numero  di  voti  sufficienti:  soluzione  "alla  MATLAB"    n_suff  =  sum(voti  >=  18);    disp(['numero  di  voti  sufficienti:  '  ,  num2str(n_suff)]);      

6. Scrivere  uno  script   che   legga  una   frase   in   ingresso  e   la   converta   in  alfabeto   farfallino.  Nota:  nell’alfabeto   farfallino   ogni   vocale   viene   sostituita   dalla   stringa   'vocale+f+vocale',   cioè:   'a'   =  'afa',  'e'  =  'efe',  'i'  =  'ifi',  'o'  =  'ofo',  'u'  =  'ufu'  

Soluzione  

farfallino.m  -­‐  script  

clear    clc    frase  =  input(['inserire  una  stringa  ']  ,  's');      far  =  [];  for  c  =  frase    

far=[far,c];    if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u')    

far  =  [far  ,'f'  ,c];    end    

end    disp([frase  ,  '  in  alfabeto  far  diventa  '  ,  far])    

Corso  di  Informatica  B/C  2014-­‐15   1-­‐8  

7. Scrivere   un   programma   (script)   che   calcoli   la   sequenza   di   Fibonacci   di   lunghezza   20,   poi  richieda   di   inserire   un   numero   2   <   n   <  4180   e   valuti   se   il   numero   è   di   Fibonacci.   Altrimenti  restituisce  il  numero  di  Fibonacci  più  vicino.  La  successione  di  Fibonacci  è  definita  così:    

F(0)  =  0  F(1)  =  1  F(n)  =  F  (n  −  1)  +  F  (n  −  2),  n  >  1    

Cioè  è  composta  dai  numeri:  0  1  1  2  3  5  8  13  21  34  ...  

Soluzione  

fibonacci.m  -­‐  script  

clear;    clc;  fibo  =  zeros(1,20);    fibo(1)  =  0;  fibo(2)  =  1;    for  i  =  3:20    

fibo(i)  =  fibo(i-­‐1)  +  fibo(i-­‐2);    end    fibo    a  =  input('Inserire  un  numero:  ');    if  sum(a  ==  fibo)  >  0    

disp([num2str(a)  'e''  un  numero  di  Fibonacci']);    else    

inferiori  =  fibo(fibo  <  a);    inferiori  =  inferiori(end);    superiori  =  fibo(fibo  >  a);    superiori  =  superiori(1);    if  superiori  -­‐  a  <  a  -­‐  inferiori    

vicino  =  superiori;    else    

vicino  =  inferiori;  end    disp(['Il  numero  didi  Fibonacci  piu''  vicino  a  '  num2str(a)  '  e''  '  num2str(vicino)]);    

end      

   

Corso  di  Informatica  B/C  2014-­‐15   1-­‐9  

8. Realizzare  uno  script  che  chieda  all’utente  due  parole  e  stampi  a  video  se  una  è  anagramma  dell’altra.    

Soluzione    

anagramma.m  -­‐  script  

clear    clc    parola1  =  input('Inserire  la  prima  parola:  ','s');    parola2  =  input('Inserire  la  seconda  parola:  ','s');    isto1  =  zeros(1,256);    isto2  =  zeros(1,256);    for  ii  =  parola1    

isto1(ii)  =  isto1(ii)  +  1;    end    for  ii  =  parola2    

isto2(ii)  =  isto2(ii)  +  1;    end    if  sum(isto1  ==  isto2)  ==  256    

disp('Le  due  parole  sono  una  l''anagramma  dell''altra');    else    

disp('Le  due  parole  non  sono  anagamma  una  dell''altra');    end    

 

9. Utilizzando  il  fatto  che  il  quadrato  di  n  è  uguale  alla  somma  dei  primi  n  numeri  dispari,  creare  uno  script  che  calcoli  il  quadrato  di  un  numero  inserito  da  utente  (n  <  100).    

Soluzione  -­‐script  

clc    clear    N  =  input('Inserire  il  numero  da  elevare  al  quadrato  (<  100):  '  );    numeri  =  2  *  [0  :  N  -­‐  1]  +  1;    c  =  1;    somma  =  0;    while  c  <=  N    

somma  =  somma  +  numeri(c);    c  =  c  +  1;    

end    fprintf('%d^2  =  %d\n',  N,  somma);        

Corso  di  Informatica  B/C  2014-­‐15   1-­‐10  

10. Realizzare  uno  script  Matlab  per:    

a. Creare   una   matrice   M   di   dimensioni   7   ×   5   contenente   0,   1,   2,   che   rappresenti   un  momento  di  una  partita  di  forza  4  in  corso.    

b. Chiedere   ai   due   giocatori,   finchè   uno   di   questi   non   inserisce   la   lettera   ’q’   (quit),   di  inserire  la  colonna  (tra  1  e  7)  dove  intende  inserire  la  propria  pedina.    

c. Inserire  la  pedina  nella  colonna  corretta  e  visualizzare  la  matrice  M  così  ottenuta.    

Soluzione  

forza4.m  -­‐  script  

clear  clc    M  =  [  0  0  0  0  0  0  0  ;...    

0  0  0  0  0  0  0  ;...    0  0  0  0  0  0  0  ;...    0  0  0  0  0  0  0  ;...    0  0  0  0  0  0  0  ];    

turno  =  1;    a  =  6;    while  (a  ~=  'q')    

disp(['E''  il  turno  del  giocatore  '  num2str(turno)]);    a  =  input('Inserire  una  giocata  (numero  di  colonna  1-­‐7)  o  uscire  (q):  ');    if  a~='q'    

if  (M(1,a)  ~=  0)    disp('Giocata  illegale');    

else    indici  =  M(:,a)  ==  0;    pos_libera  =  sum(indici);    M(pos_libera,a)  =  turno;    imagesc(M);    if  turno  ==  1    

turno  =  2;    else    

turno  =  1;    end    

end    end    

end        

Corso  di  Informatica  B/C  2014-­‐15   1-­‐11  

11. Verificare   se   una   matrice   quadrata   di   dimensione   arbitraria   è   un   quadrato   magico.   Un  quadrato   è   magico   se   la   somma   degli   elementi   sulle   righe,   sulle   colonne   e   sulla   diagonale  principale  è  la  stessa.    

Soluzione    

clear  clc  M  =  magic(4);  %M  =  randi(4,3);    [r  c]  =  size(M);    assert(r  ==  c);  %assert  controlla  se  una  condizione  è  vera.  Altrimenti  genera  un  errore      somme  =  zeros(1,2  *  r  +  1);    for  ii  =  1:r  

somme(ii)  =  sum(M(ii,:));    end      for    ii  =  (r+1):2*r    

somme(ii)  =  sum(M(:,ii-­‐r));  end    somme(2*r+1)  =  sum(diag(M));    somme      if  sum(somme  ==  somme(1))  ==  2*r+1    

disp('La  matrice  e''  un  quadrato  magico');    else    

disp('La  matrice  non  e''  un  quadrato  magico');    end        

Corso  di  Informatica  B/C  2014-­‐15   1-­‐12  

12. Data   una  matrice   20   ×   20   che   rappresenta   le   partite   di   un   campionato   di   calcio   (con   0   per  vittoria  in  casa,  1  per  pareggio  2  per  vittoria  in  trasferta  come  risultati  possibili).  Calcolare  la  classifica  finale  ordinata.    

Soluzione  

clear clc squadre = { 'Atalanta' 'Cagliari' 'Cesena' 'Chievo' 'Empoli' ' Fiorentina' 'Genoa'... 'Verona' 'Inter' 'Juventus' 'Lazio' 'Milan' 'Napoli' ' Palermo' 'Parma' 'Roma'... 'Sampdoria' 'Sassuolo' 'Torino' 'Udinese' }; squadre_alt = squadre; risultati = randi(3,20)-1; for ii = 1:20

risultati(ii,ii) = -1; end % Versione facile punti = zeros(20,1); for ii = 1:20

punti(ii) = sum(risultati(ii,:) == 0) * 3 + sum(risultati( ii,:) == 1) + ... sum(risultati(:,ii) == 2) * 3 + sum(risultati(:,ii) == 1);

end %Versione difficile punti_alt = sum(risultati == 0,2) * 3 + sum(risultati == 1,2)+… sum(risultati' == 2,2) * 3 +sum(risultati' == 1,2); %assert  controlla  se  una  condizione  è  vera.  Altrimenti  genera  un  errore assert(sum(punti == punti_alt) == 20) %forii=1:20 % disp(['La squadra ' squadre{ii} ' ha totalizzato ' num2str(punti(ii)) ' punti.']); % end %Ordiniamole while (~isempty(punti))

maxi = max(punti); trovato = 0; counter = 1; while trovato == 0

if punti(counter) == maxi disp(['La squadra ' squadre{counter} ' ha totalizzato ' num2str(punti(counter)) ' punti.' ]); punti(counter) = []; squadre(counter) = []; trovato = 1;

else

counter = counter + 1; end

Corso  di  Informatica  B/C  2014-­‐15   1-­‐13  

end end disp('-----------------------------------'); %Oppure chiediamo a MATLAB [punti_alt indici] = sort(punti_alt,'descend'); squadre_alt = squadre_alt(indici); for ii = 1:20

disp(['La squadra ' squadre_alt{ii} ' ha totalizzato ' num2str(punti_alt(ii)) ' punti.']);

end      

13. Data  una  matrice  quadrata,  leggerla  a  spirale  e  metterne  il  contenuto  in  un  vettore.    

La   lettura   a   spirale   avviene   andando   a   leggere   la   prima   riga,   poi   l’ultima   colonna,   quindi  l’ultima   riga   ed   infine   la   prima   colonna.   L’operazione   si   ripete   per   le   colonne   e   righe  progressivamente  più  interne.  

Soluzione  

clear clc %creo una matrice d’interi i cui valori sono generati randomicamente M = randi(10,7); M_old = M; riga = 1; colonna = 0; inizio = 1; fine = 0; vec = []; while(~isempty(M)) vec = [vec M(1,:)]; M(1,:) = []; if (~isempty(M)) vec = [vec M(:,end)']; M(:,end) = []; end if (~isempty(M)) vec = [vec M(end,end:-1:1)]; M(end,:) = []; end if (~isempty(M)) vec = [vec M(end:-1:1,1)']; M(:,1) = [];

Corso  di  Informatica  B/C  2014-­‐15   1-­‐14  

end end %genero un errore se qualcosa non e’ andata bene assert(sum(vec) == sum(M_old(:)));      

14. (TdE)   Dopo   una   gara   automobilistica   si   ha   come   risultato   tre   tabelle   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)  delle  tabelle  rappresenta  il  tempo  impiegato  dal  partecipante  j  per  percorrere  il  giro  i.    

Si  scrivano  le  istruzioni  per:    

• calcolare   il   tempo  totale  medio  che  è  stato   impiegato  dai  partecipanti  per  completare   la  gara;    

• determinare   il   vincitore   della   gara   (cioè   il   numero   del   partecipante   il   cui   tempo   di  percorrenza  totale  è  minore  di  quello  degli  altri  partecipanti);    

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

Soluzione  -­‐  script  

clear clc n_piloti = 10; n_giri = 30; minuti = randi(2,n_piloti,n_giri); secondi = 60 * rand(n_piloti,n_giri); millesimi = 1000 * rand(n_piloti,n_giri); tempo_medio = mean(minuti * 60 + secondi + millesimi / 1000,2); tempo_vinc = min(tempo_medio); vinc = find(tempo_medio == tempo_vinc); disp(['Il vincitore e '' ' num2str(vinc)]); figure(); plot(1:n_piloti,tempo_medio); title('Tempo medio piloti'); xlabel('Numero pilota'); ylabel('Tempo medio');  

15. (TdE)  Si  scriva  uno  script  in  Matlab  che  svolga  le  seguenti  operazioni:    

Corso  di  Informatica  B/C  2014-­‐15   1-­‐15  

• Definisce  una  matrice  quadrata  di  interi  di  dimensione  N*N,  con  N  pari  a  5.    • Acquisisce   da   tastiera   una   sequenza   di   valori   interi   che   memorizza   nella   porzione  

triangolare   superiore   della   matrice.   La   parte   triangolare   superiore   della   matrice   è  costituita  dalle  celle  poste  sulla  diagonale  principale  e  al  di  sopra  di  tale  diagonale.    

• Copia   in   un   array   di   dimensioni   opportune   tutti   I   valori   della   porzione   triangolare   di  matrice  che  sono  maggiori  di  -­‐10.    

• Stampa  il  contenuto  dell’array.    

Soluzione  

N=5; for x=1:N for y=x:N M(x,y)=input(sprintf('M(%d,%d)= ',x,y)); end end %visualizza M M l=1; for x=1:N for y=x:N if(M(x,y)>-10) a(l)=M(x,y); l=l+1; end end end % oppure a = M(M>-10)' %visualizza a %così a %oppure utilizzando disp disp(a)

 

 

16. Scrivere   uno   script   che   acquisisce   un   numero   e   verifica   se   è   primo   o  meno   stampando   un  apposito  messaggio  a  video.    

Soluzione  

n = input('valore: '); d = 2:n/2; mod(n,d) if all(mod(n,d)) %alternativa: ~any(mod(n,d)==0) disp([num2str(n) ' è primo']); else disp([num2str(n) ' non è primo']); end

Corso  di  Informatica  B/C  2014-­‐15   1-­‐16  

     

Corso  di  Informatica  B/C  2014-­‐15   1-­‐17  

17. Si   vuole   realizzare   uno   script   per   analizzare   i   voti   conseguiti   da   una   serie   di   studenti   in   un  esame,   partendo   dai   punteggi   conseguiti   in   ciascun   esercizio.   I   dati   di   partenza   sono  memorizzati   in   un   file,   il   cui   va   chiesto   il   nome   all'utente,   e   sono   organizzati   nel   seguente  modo:  la  prima  riga  del  file  contiene  i  punti  massimi  per  ciascuno  degli  esercizi  dell'esame  e  le  successive  righe  i  punteggi  conseguiti  da  ciascuno  degli  studenti  che  ha  partecipato  all'esame.  Un  esempio  di  file  è:  5  5  6  4  2  8  1  2  2  2  2  2  5  5  4  4  2  8  5  5  5  3  2  5      5  5  5  1  2  1  

dove  l'esame  era  composto  da  6  esercizi  ed  è  stato  sostenuto  da  4  studenti  (gli  studenti  sono  identificati  con  un  indice  progressivo,  es:  1,2,3,4).    Lo  script  deve  eseguire  le  seguenti  elaborazioni:  • leggere  i  dati  e  salvarli  in  due  matrici  (una  per  i  punti  massimi  ed  una  per  i  punteggi  degli  

studenti)  • verificare  che  i  punteggi  siano  consistenti:  un  punteggio  di  un  esercizio  non  è  consistente  

se  non   compreso   tra   0   ed   il   punteggio  massimo   conseguibile   (per   esempio  per   il   primo  esercizio  dell'esempio  sopra  il  punteggio  deve  essere  compreso  tra  0  e  5,  estremi  inclusi).  Un  esempio  di  file  inconsistente  è  il  seguente:  

5  5  6  4  2  8  7  2  2  2  2  2  5  5  4  4  2  8  5  5  5  3  2  5      

 SE  è  stata  identificata  almeno  un'inconsistenza  riportare:  • il  numero  di  studenti  con  almeno  un  punteggio  inconsistente  • i   dati   degli   studenti   che   presentano   un'inconsistenza   (in   particolare   visualizzare   l'indice  

dello  studente  ed  i  suoi  punteggi)    ALTRIMENTI  eseguire  le  seguenti  elaborazioni:  • calcolare  i  voti  • contare  il  numero  di  studenti  promossi  • calcolare  i  voti  massimo  e  minimo  conseguiti  dagli  studenti  promossi  • contare   il   numero   di   voti   scarsi   (cioè   compresi   nell'intervallo   [18;21]),   di   voti   mediocri  

(voti  nell'intervallo  [22;25])  e  di  voti  buoni  (voti  nell'intervallo  [26;30])  • cercare   e   visualizzare   gli   indici   gli   studenti   che   hanno   almeno   un   esercizio   insufficiente  

(sufficienza  al  50%  del  punteggio  massimo)  • individuare  quale  esercizio   (o   insieme  di  esercizi)  è  andato   in  media  peggio   (per  ciascun  

esercizio  bisogna  calcolare  il  rapporto  tra  il  punteggio  medio  conseguito  dagli  studenti  ed  il  punteggio  massimo)  

Corso  di  Informatica  B/C  2014-­‐15   1-­‐18  

Soluzione  

%caricare punteggi da un file di testo %(prima riga punteggi massimi poi punteggi di ciascuno studente %salvare in due strutture punteggi massimi da punteggi studenti nomefile=input('inserire nome file: ','s'); dati=load(nomefile); punti=dati(1,:); punteggi=dati(2:end,:); [nstudenti nesercizi]=size(punteggi); %controllare se ci sono voti inconsistenti %contare inconsistenze e stampare il seguente report: %numero inconsistenze e lista studenti con dati inconsistenti ninconsistenti=0; inconsistenti=[]; for ii=1:nstudenti if any(punti<punteggi(ii,:) | punteggi(ii,:)<0) ninconsistenti=ninconsistenti+1; inconsistenti(ninconsistenti)=ii; end end disp(['inconsistenti: ' num2str(ninconsistenti)]); if ninconsistenti>0 disp('max punti: '); disp(num2str(punti)); disp('report inconsistenti: '); for ii=1:length(inconsistenti) disp([num2str(inconsistenti(ii)) ': ' num2str(punteggi(ii,:))]); end else %se ok calcolare voti. contare max, min (non bocciato), numero bocciati %e fare statistiche sui presenti... voti=sum(punteggi'); votomax=max(voti); nbocciati=sum(voti<18); votomin=min(voti(voti>=18)); numscarsi=sum(voti>=18 & voti<22); nummedi=sum(voti>=22 & voti<26); numbuoni=sum(voti>=26); disp(['bocciati : ' num2str(nbocciati)]); disp(['max voto : ' num2str(votomax)]); disp(['min voto : ' num2str(votomin)]); disp(['scarsi: ' num2str(numscarsi) ', discreti: ' num2str(nummedi) ', buoni:' num2str(numbuoni) ]); %cercare gli studenti che hanno almeno un esercizio insufficiente %insufficienza: (punteggio<punteggio_massimo/2) nStudEsInsuf=0;

Corso  di  Informatica  B/C  2014-­‐15   1-­‐19  

studEsInsuf=[]; for ii=1:nstudenti if any(punteggi(ii,:)<punti./2) nStudEsInsuf=nStudEsInsuf+1; studEsInsuf(nStudEsInsuf)=ii; end end disp(['studenti con almeno un es insuff: ' num2str(studEsInsuf)]); %vedere quale esercizio è andato in media peggio mediaPunteggi=sum(punteggi)./nstudenti; disp(['max punteggi: ' num2str(punti)]); disp(['media punteggi: ' num2str(mediaPunteggi)]); percPunteggi=mediaPunteggi./punti; percPeggio=min(percPunteggi); numeroEsercizio=1:nesercizi; numEsPeggio=numeroEsercizio(percPunteggi==percPeggio); disp(['esercizio peggiore: ' num2str(numEsPeggio)]); %in alternativa: %disp(['esercizio peggiore: ' num2str(find(percPunteggi==percPeggio))]); end  

     

Corso  di  Informatica  B/C  2014-­‐15   2-­‐20  

Chapter  2 Funzioni    

1. Realizzare   uno   script   MATLAB   che   richieda   all’utente   l’inserimento   due   parole   e   stampi   a  video  se  una  è  anagramma  dell’altra.    

Soluzione  

anagramma.m  -­‐  script  

% Anagramma: versione con funzioni. % leggere 2 parole da tastiera % [parola1, parola2] = leggi_parole(); % costruire gli istogrammi secondo l'alfabeto ASCII esteso (256 simboli) % h1 = calcola_istogramma(parola1); h2 = calcola_istogramma(parola2); % visualizzare gli istogrammi come grafici a barre % figure, bar(h1) figure, bar(h2) % calcolare se si tratta di anagrammi % anagrammi = sono_anagrammi(h1, h2); if (anagrammi) fprintf('Le due parole sono anagrammi\n'); else fprintf('Le due parole NON sono anagrammi\n'); end

 

leggi_parole.m  -­‐  funzione  

function [p1, p2] = leggi_parole() p1 = input('Inserici una parola o frase: ', 's'); p2 = input('Inserici una parola o frase: ', 's');    

   

Corso  di  Informatica  B/C  2014-­‐15   2-­‐21  

 

calcola_istogramma.m  -­‐  funzione  

function [h] = calcola_istogramma(parola) h = zeros(1, 256); for c = parola h(c) = h(c) + 1; end

 

sono_anagrammi.m  -­‐  funzione  

function [an] = sono_anagrammi(h1, h2) % assumo che gli istogrammi abbiano la stessa dimensione % soluzione alla C an = 1; %vero ii = 1; while an && ii < length(h1) an = h1(ii) == h2(ii); ii = ii + 1; end % soluzione alla MATLAB an = all(h1 == h2); % an = ~any(h1 ~= h2);  

 

   

Corso  di  Informatica  B/C  2014-­‐15   2-­‐22  

2. (TdE)  Scrivere  un  programma  che:  1. acquisisca   un   numero   da   tastiera   e   continui   a   richiedere   l'inserimento   finché   il   numero  

inserito  continui  a  non  essere  intero  positivo  2. verificare  se  il  numero  intero  positivo  acquisito  è  perfetto,  abbondante  o  difettivo:  

• Perfetto:  numero  i  cui  divisori  positivi  (escluso  il  numero  stesso),  sommano  al  numero  stesso.  

• Abbondante:  numero  i  cui  divisori  positivi  (escluso  il  numero  stesso),  sommano  ad  un  numero  maggiore  del  numero  stesso.  

• Difettivo:  se  non  è  perfetto  e  non  è  abbondante.  3. se   il   numero   non   è   perfetto,   controllare   se   è   abbondante   o   difettivo   e   stampare   un  

messaggio  a  video  che  lo  dica.  4. inoltre,  nel  caso  3.,  richiedere  anche  un  altro  numero  intero  positivo  b,  e  controllare  se  a  e  

b  sono  amici:  • Amici:   due   numeri   sono   amici   quando   la   somma   dei   divisori   del   primo   (escluso   il  

numero  stesso)  coincide  al  secondo  numero;  e  viceversa.  5. Scrivere  un  programma  che  elenchi  i  primi  k  numeri  abbondanti,  con  k  definito  dall'utente.  

Soluzione  

divisori.m  -­‐  script    

clc clear % inserimento di un numero positivo % a = leggi_intero_positivo(); % a questo punto il numero inserito e` senz'altro positivo % calcolo se il numero e` perfetto, abbondante o difettivo [perfetto, abbondante] = numero_perfetto(a); % se perfetto, allora stampo che e` perfetto e concludo if (perfetto == 1) disp([num2str(a), ' e` perfetto']); else % altrimenti % controllo se e` abbondante o difettivo % if (abbondante == 1) disp([num2str(a), ' e` abbondante']); else disp([num2str(a), ' e` difettivo']); end % acquisisco un altro numero, riusando la funzione b = leggi_intero_positivo(); % a e b sono amici? amici = sono_amici(a, b); if (amici == 1)

Corso  di  Informatica  B/C  2014-­‐15   2-­‐23  

disp([num2str(a), ' e ', num2str(b), ' sono amici']); else disp([num2str(a), ' e ', num2str(b), ' NON sono amici']); end end  

 

leggi_intero_positivo.m  -­‐  funzione  

function [n] = leggi_intero_positivo() n = 0; while n <= 0 n = input('Inserisci un numero intero positivo: '); end  

 

numero_perfetto.m  -­‐  funzione  

function [perfetto, abbondante] = numero_perfetto(n) % calcolo la somma dei divisori (escluso il numero stesso) somma = somma_divisori(n); % calcolo se la somma dei divisori coincide col numero stesso perfetto = (n == somma); % calcolo se il numero e` maggiore della somma dei suoi divisori (abbondante) abbondante = n > somma; % alla fine dell'esecuzione di questa funzione, le variabili 'perfetto' e 'abbondante' saranno disponibili al programma chiamante.  

 

somma_divisori.m  -­‐  funzione  

function somma = somma_divisori(n) % soluzione alla C, non raccomandata somma = 0; for d = 1:n/2 if (~mod(n, d)) % mod(n, d) == 0 somma = somma + d; end end % soluzione alla MATLAB %

Corso  di  Informatica  B/C  2014-­‐15   2-­‐24  

divisori = 1:n/2; resti = mod(n, divisori); divisori_interi = divisori(resti == 0); somma = sum(divisori); % soluzione compatta % somma = sum(divisori(mod(n, divisori) == 0));  

 

sono_amici  -­‐    funzione  

function amici = sono_amici(a, b) amici = (somma_divisori(a) == b) && (somma_divisori(b) == a); % end funzione sono_amici  

 

elenca_k_abbondanti  -­‐  script  

clear; clc; % inserimento di un numero positivo attraverso la chiamata della funzione % k = leggi_intero_positivo(); for i = 1:k [perfetto, abbondante] = numero_perfetto(i); if (abbondante) disp([ num2str(i), ' e'' abbondante']) end end  

 

   

Corso  di  Informatica  B/C  2014-­‐15   2-­‐25  

3. (TdE)  Scrivere  una  funzione  che,  ricevendo  in  ingresso  una  matrice  M  di  numeri,  restituisce  in  uscita  una  matrice  MR,  ottenuta  da  M  nel  seguente  modo:  • si  calcola  la  media  aritmetica  dei  valori  di  M  • per  i  valori  che  in  M  sono  minori  della  media,  in  MR  si  pone  nella  posizione  corrispondente  

il  valore  -­‐1,  • per  quelli  superiori  alla  media  si  pone  il  valore  1,    • per  gli  altri  (quelli  uguali  alla  media)  si  pone  lo  stesso  valore  in  M.  

Soluzione  

transformMatrix.m  -­‐  funzione  

function [MR] = transformMatrix(M) media = mean(mean(M)); MR = M; MR(MR < media) = -1; MR(MR > media) = 1; % fine funzione transformMatrix % soluzione alla C [R, C] = size(M); media = 0; % somma di tutti gli elementi for r = 1:R for c = 1:C media = media + M(r,c); end end % calcolo media media = media / (R * C); % generazione MR elemento per elemento for r = 1:R for c = 1:C if M(r,c) < media MR(r,c) = -1; else if M(r,c) > media MR(r,c) = 1; else MR(r,c) = M(r,c); end end end end

 

   

Corso  di  Informatica  B/C  2014-­‐15   2-­‐26  

4. (TdE)   Scrivere   un   programma   per   la   gestione   di   un   magazzino   dove   ogni   prodotto   nel  magazzino  è  univocamente  identificato  da  un  barcode  (un  numero  intero)  e  da  una  tipologia  (un  carattere).  Il  software  di  gestione  associa  ad  ogni  prodotto  due  numeri,   il  primo  che  indica  il  numero  di  pezzi  in  stock  il  secondo  che  indica  il  numero  di  pezzi  ordinati.    Si   ipotizzi   che   barcode,   tipo,   stock,   ordine   siano   4   vettori,   già   popolati,   contenenti   tutte   le  informazioni  necessarie  per  la  gestione  del  magazzino.  (l'i-­‐simo  elemento  di  stock  e  di  ordine  rappresentano   le  quantità  relative  al  prodotto  a  cui  è  associato  l'i-­‐simo  elemento  di  barcode).  Ad  esempio:    barcodes  =    [123  ;  1312  ;  12312  ;  1231  ;  99123];  tipo                    =    ['A'  ;  'A'    ;  'X'      ;  'W'    ;  'W'    ];  stock     =    [0      ;  300    ;  5          ;  6        ;  0        ];  ordine     =    [23    ;  100    ;  2          ;  100    ;  0        ];    Si  scriva:  

a. la   funzione   “ricerca”   che   prende   in   ingresso   un   barcode   e   restituisce   un  messaggio  contenente   il   tipo   di   prodotto,   il   numero   di   pezzi   in   stock   ed   in   ordine.   In   caso   di  multiple  occorrenze,  scegliere  la  prima.    

b. un  esempio  di  chiamata  alla  funzione  "ricerca".  c. la   funzione   “ricercaMancanti”   che,   a   seconda   di   un   parametro   P,   restituisca   al  

programma  chiamante  un  vettore  contenente  I  codici  a  barre  dei  prodotti:  • (se  P  =  0)  non  presenti  in  stock  ma  in  ordine,    • (se  P  =  1)  non  presenti  in  stock  che  non  sono  nemmeno  in  ordine,  • (se  P  =  2)  per  cui  ci  sono  più  pezzi  in  ordine  che  attualmente  in  stock.  

d. Scrivere  un  esempio  di  chiamata  alla  funzione  ricercaMancanti.  e. Si  scriva  la  funzione  “aggiungiProdotto”,  che  permette  di  aggiungere  al  magazzino  un    

nuovo  prodotto  (barcode  +  stock  +  ordine).  f. Scrivere  un  esempio  di  chiamata  alla  funzione  aggiungiProdotto.  

Soluzione  

ricerca.m  –  funzione  

% definizione funzioni function [msg] = ricerca (b, t, s, o, bc) bc_indici = find(b == bc); b = b(bc_indici)(1); t = t(bc_indici)(1); s = s(bc_indici)(1); o = o(bc_indici)(1);

Corso  di  Informatica  B/C  2014-­‐15   2-­‐27  

msg = ['il prodotto corrispondente al codice a barre ', num2str(bc), ' e` di tipo ',num2str(t), ' elementi in stock: ', num2str(s),' in ordine: ', num2str(o) ]; end    

ricercaMancanti.m  -­‐  funzione  

function [prodotti] = ricercaMancanti(b, t, s, o, P) switch P case 0 bc_indici = find(s == 0 && o > 0); case 1 bc_indici = find(s == 0 && o == 0); case 2 bc_indici = find(o > s); end prodotti = b(bc_indici) end    

aggiungiProdotto.m  -­‐  funzione  

function [b, t, s, o] = aggiungiProdotto(b, t, s, o, n_b, n_t ,n_s, n_o) b = [b; n_b]; t = [t; n_t]; s = [s; n_s]; o = [o; n_o]; end  

Esempi  d’uso  delle  funzioni  

% main barcodes = [123 ; 1312 ; 12312 ; 1231 ; 99123]; tipo = ['A' ; 'A' ; 'X' ; 'W' ; 'W' ]; stock = [0 ; 300 ; 5 ; 6 ; 0 ]; ordine = [23 ; 100 ; 2 ; 100 ; 0 ]; ricerca(barcodes, tipo, stock, ordine, 12312) ricercaMancanti(barcodes, tipo, stock, ordine, 0) ricercaMancanti(barcodes, tipo, stock, ordine, 1) ricercaMancanti(barcodes, tipo, stock, ordine, 2) [barcodes, tipo, stock, ordine] = aggiungiProdotto(barcodes, tipo, stop, ordine, 999, 'F', 3, 24)        

Corso  di  Informatica  B/C  2014-­‐15   2-­‐28  

5. Si   scriva  una   funzione  che   legga  una  parola  e   restituisca  1   se   tale  parola  è  palindroma,   zero  altrimenti.  Fornire  un  esempio  di  chiamata  della  funzione.  

Soluzione  

palindroma.m  -­‐  funzione  

function [pal] = palindroma(par) % soluzione "alla C" len = size(par, 2); pal = 1; ii = 1; while((ii <= len / 2 ) && pal) if(par(ii) ~= par(end - ii + 1)) pal = 0; end ii = ii + 1; end % soluzione "alla MATLAB" parAlContrario = par(end : -1 : 1); corrispondenze = (par == parAlContrario); if(sum(corrispondenze == size(par, 2))) pal = 1; else pal = 0; end % alternativa super-compatta pal = sum(par == par(end : -1 : 1))== size(par, 2);

 

Esempio  di  chiamata  della  funzione  –  script    

% acquisisco la parola% parola = input('inserire parola ' , 's'); % chiamo la funzione % pal = palindroma(parola); str = [parola]; if (pal) str = [str , ' è ']; else str = [str , ' NON è ']; end disp([str , ' palindroma']);        

Corso  di  Informatica  B/C  2014-­‐15   2-­‐29  

6. (TdE)  Una  matrice  contiene  numeri   interi.  Si  vuole  progettare  una  funzione  che,  ricevendo  la  matrice   e   un   array   di   numeri   interi   che   rappresenta   una   sequenza,   cerchi   tale   sequenza  all'interno   della   matrice.   La   sequenza   cercata   può   essere   disposta,   nella   matrice,  verticalmente  dall'alto  verso  il  basso  od  orizzontalmente,  da  sinistra  verso  destra.  La  funzione  deve  avere  la  seguente  intestazione:  

  function  [riga,  col,  dir]  =  cerca_sequenza(matrice,  seq)  

se   la   sequenza   è   presente   nella   matrice   allora   `riga`   e   `col`   indicano   gli   indici   di   riga   e   di  colonna   del   suo   primo   elemento,   mentre   `dir`   viene   posto   uguale   al   carattere   'v'   se   la  sequenza  è  disposta  verticalmente,  'o'  se  orizzontalmente  (se  la  sequenza  è  presente  ripetuta  in  più  posizioni,  i  valori  restituiti  possono  essere  quelli  relativi  a  una  qualsiasi  delle  ripetizioni);  se  la  sequenza  non  è  presente,  `riga`  e  `col`  valgono  entrambi  0  e  dir  vale  'n'.  

Per  codificare  la  funzione  in  questione,  si  sviluppi  prima  la  seguente  funzione  ausiliaria  

  function  [pres]  =  verifica_orizzontale_da_posizione(matrice,  seq,  riga,  col)  

che  ricerca   la  sequenza  nella  matrice  a  partire  da  una  posizione  d’inizio  precisa,   in  direzione  orizzontale:  riga  e  col  sono  il  punto  di  inizio;  il  risultato  [pres]  vale  1  se  la  sequenza  è  presente,  0  altrimenti.  

Successivamente  si  utilizzi  tale  funzione  per  codificare  la  seguente:  

  function  [riga,  col]  =  cerca_inizio_orizzontale(matrice,  seq)  

mentre  la  versione  verticale  può  essere  facilmente  derivata  dalla  precedente  

  function  [riga,  col]  =  cerca_inizio_verticale(matrice,  seq)  

Queste  funzioni  cercano  la  sequenza  in  tutta  la  matrice  con  disposizione  orizzontale  e  verticale,  restituendo   in   riga   e   col   le   coordinate   del   punto   d’inizio,   se   la   sequenza   viene   trovata,   o   il  valore  0  altrimenti.  

Soluzione  

verifica_orizzontale_da_posizione.m  -­‐  funzione  

function [pres] = verifica_orizzontale_da_posizione(matrice, seq, riga, col) len = length(seq); % calcolo la lunghezza della sequenza % estraggo una porzione di matrice a partire da riga,colonna fino a % riga,colonna+len-1 porzione = matrice(riga, col:col+len-1); % se la porzione coincide con la sequenza, la sequenza e` trovata pres = all(porzione == seq);    

Corso  di  Informatica  B/C  2014-­‐15   2-­‐30  

cerca_inizio_orizzontale.m  -­‐  funzione  

function [riga, col] = cerca_inizio_orizzontale(matrice, seq) [R, C] = size(matrice); len = length(seq); for r = 1:R % per ogni riga for c = 1:C-len+1 % per ogni colonna (tenendo conto della

% lunghezza della sequenza) % cerca la sequenza orizzontalmente pres = verifica_orizzontale_da_posizione(matrice, seq, r, c); % se trovata, salva riga e colonna, poi ritorna if pres riga = r; col = c; return; end end end

 

cerca_inizio_verticale.m  -­‐  funzione  

function [riga, col] = cerca_inizio_verticale(matrice, seq) [col, riga] = cerca_inizio_orizzontale(matrice', seq);

 

cerca_sequenza.m  -­‐  funzione  

function [riga, col, dir] = cerca_sequenza(matrice, seq) % non trovato riga = 0; col = 0; dir = 'n'; % ricerca orizzontale [r, c] = cerca_inizio_orizzontale(matrice, seq); if r ~= 0 riga = r; col = c; dir = 'o'; return; end % ricerca verticale [r, c] = cerca_inizio_verticale(matrice, seq); if r ~= 0 riga = r; col = c; dir = 'v'; return; end

Corso  di  Informatica  B/C  2014-­‐15   2-­‐31  

8. In  algebra  lineare  la  matrice  compagna  di  un  polinomio  di  grado  N:  

 

è  una  matrice  quadrata  NxN  avente:  

• 1  sulla  prima  sovra-­‐diagonale  • i  coefficienti,  cambiati  di  segno,  sull'ultima  riga  • 0  (zero)  altrove  

 

 

 

 

Scrivere  una  funzione  che,  ricevuto  in  ingresso  il  vettore  dei  coefficienti  

,     restituisca  la  corrispondente  matrice  compagna.  

Soluzione  

matriceCompagna.m  –  funzione  

% function CP = matriceCompagna(coefficienti) % leggo la lunghezza del vettore n = length(coefficienti); % preparo una matrice NxN di zeri CP = zeros(n); % seleziono la sovradiagonale % % leggo la matrice per colonne: % * il primo elemento della sovra-diagonale e` n + 1 % * i successivi elementi sono tutti distanti n + 1 % * mi fermo alla fine della matrice CP(n+1:n+1:end) = 1; %oppure in maniera piu’ compatta CP = diag(ones(n-1,1), 1); % assegno all'ultima riga i coefficienti cambiati di segno CP(n,1:n) = -coefficienti;

 

c0 + c1x+ c2x2 + · · ·+ cN�1x

N�1

⇥c0 c1 c2 . . . cN�1

2

66664

0 1 0 · · · 00 0 1 · · · 0· · · · · · · · · · · · · · ·0 0 0 · · · 1

�c0 �c1 �c2 · · · �cN�1

3

77775

Corso  di  Informatica  B/C  2014-­‐15   2-­‐32  

9. Si  implementi  la  funzione  “calcolaRischio”,  che  riceva  in  ingresso:  • un  vettore  “profiloArgine”  che  contiene  le  altezze  dell’argine  di  un  fiume,  in  metri  rispetto  

al  fondo  del  letto  del  fiume;  in  vari  punti  del  corso  del  fiume  a  distanze  crescenti.  • l’altezza   attuale   del   livello   dell'acqua   del   fiume,   in  metri   rispetto   al   fondo   del   letto   del  

fiume.  • i  millimetri   di   incremento   totale   di   altezza   del   fiume   dovuti   alla   pioggia   prevista   per   la  

giornata.  • Calcoli  i  punti  del  profilo  a  rischio  esondazione,  cioè  quelli  per  cui:  

profiloArgine  <=  altezzaFiume  +  (mmIncrementoPrevisto  /  1000)    

Si  realizzi  uno  script  che    

a) richiami  la  funzione  calcolaRischio  sviluppata  al  punto  precedente;  b) visualizzi  sullo  schermo  un  grafico  che  mostri:  

• l’andamento  del  profilo  dell’argine  • il  livello  attuale  del  fiume  • i  punti  dell’argine  a  rischio  di  esondazione  

c) generi   e   visualizzi   a   video   una   tabella   contenente   i   soli   punti   dell’argine   a   rischio   di  esondazione  

• prima  colonna:  distanza  del  punto  a  rischio  in  metri  dalla  foce  • seconda  colonna:  altezza  dell’argine  in  quel  punto  • terza   colonna:  minuti   che   passeranno   tra   il   rilevamento   e   l’esondazione   in   quel  

punto  

minuti  =  (profiloArgine  -­‐  altezzaFiume)  *  1000  /  (mmIncrementoPrevisto  /  24  *  60)]  

Soluzione  

calcolaRischio.m  –  funzione  

function rischio = calcolaRischio(profiloArgine, altezzaFiume, mmIncrementoPrevisto) % % input: % profiloArgine: vettore contenente l’altezza dei punti dell’argine % altezzaFiume: scalare contenente il valore dell’altezza attuale del fiume % mmIncrementoPrevisto: scalare contenente il valore dell’incremento di altezza previsto del fiume rischio=find(profiloArgine<=altezzaFiume+(mmIncrementoPrevisto/1000));  

argine.m  –  funzione  

Corso  di  Informatica  B/C  2014-­‐15   2-­‐33  

% dati di esempio profiloArgine = [10 10 10 9 8 8 7 10 11 14 20 12 3]; nCampioni = length(profiloArgine); % si supponga che il profilo sia già creato % leggiamo l'altezza altezzaFiume = input('Altezza attuale del fiume in metri: '); % dominio (in metri) x = 1:nCampioni; % costante, altezza del fiume yAltezza = zeros(1, nCampioni); % assegno il valore dell'altezza (supponiamo letto da tastiera) yAltezza(:) = altezzaFiume; % plot del profilo dell'argine plot(x, profiloArgine); hold on % plot dell'atezza (costante) plot(x, yAltezza); % plot dei punti a richio convertendo i mm in metri plot(puntiARischio, altezzaFiume + mmIncrementoPrevisto /1000, '*'); hold off % la tabella avrà [metri, profiloArgine, minuti] % metri metri = x; % minuti minuti = 1000 * 24 * 60 * abs(profiloArgine - altezzaFiume) / (mmIncrementoPrevisto); % creo la tabella tabella = [metri', profiloArgine, minuti]; % seleziono solo i punti a rischio (tutte le colonne) tabella = tabella(puntiARischio, :); % visualizzo disp(tabella);

Corso  di  Informatica  B/C  2014-­‐15   2-­‐34  

10. La   logistic  map  è  una   sequenza  di   numeri   reali   x(0),   x(1),   x(2),   ...,   tali   che,   per  ogni   numero  intero  naturale  n,  si  ha  che:      

x(n+1)  =r  *  x(n)  *  [1-­‐x(n)]  

dove  0  <  x(0)  <  1  e  r  >  0  è  un  numero  reale.    

Per   esempio,   prendendo   x(0)   =   0.2   e   r   =   3.2,   i   primi   quattro   numeri   della   sequenza   sono:  0.2000  0.5120  0.7995  0.5129  

Scrivere  la  funzione  con  la  seguente  intestazione:  

function  [x,  rip]  =  logisticMap(x0,  r,  lun)  

che,   ricevendo   il   primo   valore   x(0)   della   sequenza,   il   coefficiente   r,   e   un   valore   lun  rappresentante   la   possibile   lunghezza   di   sequenza,   calcola   in   successione   gli   elementi   della  logistic  map,  fino  a  un  numero  massimo  di  lun  elementi,  e  li  inserisce  nel  vettore  x.  

Durante   la  generazione  della   sequenza,   se  prima  di   raggiungere   il  numero  di  elementi   lun  si  ottiene   un   elemento   già   generato   in   precedenza,   allora   il   vettore   x   viene   riempito   con   gli  elementi   fino   a   quello   ripetuto   (incluso)   e   il   parametro   rip   viene   posto   a   1.   Se   nessun  elemento   si   ripete,   il   vettore   x   viene   riempito   con   i   primi   lun   elementi   della   sequenza,   e   il  parametro  rip  viene  posto  a  0.  

Per  esempio,  con  la  chiamata:  

[a  b]  =  logisticMap(0.3,  2,  10)  

si  ottiene:  

a  =  0.3000  0.4200  0.4872  0.4997,  0.5000,  0.5000     b  =  1  

mentre  con  la  chiamata:  

[a  b]  =  logisticMap(0.3,  1.3,  8)  

si  ottiene:  

a  =  0.3000  0.2730  0.2580  0.2489  0.2430  0.2391  0.2365  0.2348     b  =  0  

   

Corso  di  Informatica  B/C  2014-­‐15   2-­‐35  

Soluzione  

logisticMap.m  –  funzione    

function [x, rip] = logisticMap(x0, r, lun) x = x0; % continua mentre la lunghezza non e` stata raggiunta while length(x) < lun % l'elemento successivo al corrente e` determinato dalla formula % % con x(length(x)) prendiamo l'ultimo elemento x(n) % ovvero x(end), se preferite x1 = r * x(length(x)) * (1 - x(length(x))); % controllo se gia` generato if any(abs(x-x1) <= 0.0001) % riporto a 1 rip = 1; % inserisco l'elemento % % identico a x = [x, x1]; x(length(x) + 1) = x1; % ritorno immediatamente return; else % inserisco l'elemento % % identico a x = [x, x1]; x(length(x) + 1) = x1; end end % riporto a zero in tutti gli altri casi rip = 0; end  

   

Corso  di  Informatica  B/C  2014-­‐15   2-­‐36  

11. (TdE)   Scrivere   una   funzione   che   prende   come   parametro   due   matrici   A   e   B,   delle   stesse  dimensioni,  e  restituisce  i  seguenti  3  valori:  

• Il  numero  totale  di  elementi  uguali  in  posizioni  corrispondenti.  • Il  numero  di  elementi  di  A  massimali  per  la  matrice  B,  cioè  il  numero  di  posizioni,  nella  

matrice  A,   in  cui  è  presente  un  numero  che  è  maggiore  o  uguale  a   tutti  gli  elementi  presenti  nella  matrice  B.  

• Il  numero  massimo  di  elementi  di  A  massimali  per  la  matrice  B  (secondo  la  definizione  precedente)  presenti  in  ogni  colonna  della  matrice  A.  

Soluzione  

massimali.m  -­‐  funzione  

function [r1 r2 r3] = massimali(A, B) % r1 % elementi uguali in posizioni corrispondenti t1 = A == B; r1 = sum(sum(t1)); % r2 % cerchiamo il massimo in B M = max(max(B)); % i numeri di A maggiori di M saranno maggiori (o uguali) a % tutti gli altri elementi di B (in quanto M è il massimo) t2 = A >= M; r2 = sum(sum(t2)); % r3 % somma lungo le righe tutti gli elementi massimali sc = sum(t2); % cerco il massimo r3 = max(sc);  

   

Corso  di  Informatica  B/C  2014-­‐15   2-­‐37  

12. Si  richiede  di  progettare  e  scrivere  una  funzione  che,  dato  N  un  numero  intero  positivo,  senza  fare   uso  di   ricorsione   e   usando   al  massimo  un   ciclo   (e.g.,   for,  while)   costruisca   una  matrice  quadrata  di  dimensioni  N*2  x  N*2  con  il  seguente  schema:    (esempio  per  N  =  5)  

 

 

 

 

 

 

Punto  facoltativo,  ottenere  la  seguente  matrice:  

 

 

 

 

 

 

Soluzione  

frame.m  –  funzione  

function [M] = frame(n) n = 2 * n; % raddoppio n M = zeros(n); % parto da una matrice di soli zeri" for ii = 1:n % per ogni sottomatrice "centrata M(ii:n-ii+1, ii:n-ii+1) = M(ii:n-ii+1, ii:n-ii+1) + 1; % alternativamente M(ii:n-ii+1, ii:n-ii+1) = ii; e non serve inizializzare a zeros(); % punto facoltativo, ritocco gli angoli M([ii, n-ii+1], [ii, n-ii+1]) = -1; end  

   

2

666666666666664

1 1 1 1 1 1 1 1 1 11 2 2 2 2 2 2 2 2 11 2 3 3 3 3 3 3 2 11 2 3 4 4 4 4 3 2 11 2 3 4 5 5 4 3 2 11 2 3 4 5 5 4 3 2 11 2 3 4 4 4 4 3 2 11 2 3 3 3 3 3 3 2 11 2 2 2 2 2 2 2 2 11 1 1 1 1 1 1 1 1 1

3

777777777777775

2

666666666666664

�1 1 1 1 1 1 1 1 1 �11 �1 2 2 2 2 2 2 �1 11 2 �1 3 3 3 3 �1 2 11 2 3 �1 4 4 �1 3 2 11 2 3 4 �1 �1 4 3 2 11 2 3 4 �1 �1 4 3 2 11 2 3 �1 4 4 �1 3 2 11 2 �1 3 3 3 3 �1 2 11 �1 2 2 2 2 2 2 �1 1�1 1 1 1 1 1 1 1 1 �1

3

777777777777775

Corso  di  Informatica  B/C  2014-­‐15   2-­‐38  

13. Il   sig.   Rossi   ha   ottenuto  un   finanziamento  di   100000   euro.  Ha   scelto   una   formula   con   tasso  fisso  al  5%,  quindi  ogni  mese,  per  N  anni,  dovrà  pagare  una   rata  mensile.   La   rata  mensile  è  composta  di  una  quota  capitale  più  una  quota  d’interessi.  La  quota  capitale  è  fissata  in  modo  tale   che   la   somma  di   tutte   le  quote   capitali  dia   l'ammontare   finanziato,  mentre  gli   interessi  sono   calcolati   in   base   al   residuo   del  mese   precedente.   Al   primo  mese   il   residuo   è   il   totale  finanziato.  Il  tasso  dato  è  annuo  e  va  diviso  per  il  numero  di  mesi.  Implementare  la  seguente  funzione  (formula  ammortamento  all'italiana):  

[rata  residuo  interessi]  =  calcola_amm(finanziamento,  tasso,  anni)  

che   calcola   il   piano   di   ammortamento   su   un   numero   di   anni   indicato   come   parametro   (ad  esempio,  anni  =  3).  

Se  ad  esempio  il  finanziato  è  pari  a  500  euro,  con  un  tasso  annuo  del  12%  si  ottiene  in  1  anno:  Rata              Residuo              Interessi  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  46.66667      458.33333          5.00000  46.25000      416.66667          4.58333  45.83333      375.00000          4.16667  45.41667      333.33333          3.75000  45.00000      291.66667          3.33333  44.58333      250.00000          2.91667  44.16667      208.33333          2.50000  43.75000      166.66667          2.08333  43.33333      125.00000          1.66667  42.91667      83.33333              1.25000  42.50000      41.66667              0.83333  42.08333      0.00000                  0.41667  

E  sommando  le  rate  si  ottiene  un  importo  totale  di  532.50  euro.  

Soluzione  

calcola_amm.m  –  funzione  

function [rata residuo interessi] = calcola_amm(finanziamento, tasso, anni) % il tasso è da dividere per il numero di mesi in ogni anno, %perchè la rata è mensile tasso = (tasso/12)/100; % la quota capitale è fissa ogni mese n_rate = anni*12; qc = finanziamento/(n_rate); % il capitale residuo è pari, ogni mese, al finanziamento meno %k * qc, dove k è il numero del mese corrente residuo(1:n_rate) = finanziamento - [1:n_rate] * qc;

Corso  di  Informatica  B/C  2014-­‐15   2-­‐39  

% gli interessi del primo mese sono basati sul finanziamento % iniziale interessi(1) = finanziamento * tasso; % mentre per i seguenti 2:n_rate-1 si prende semplicemente il % residuo e lo si moltiplica per il tasso interessi(2:n_rate) = residuo(1:n_rate-1) * tasso; % per la rata si somma quota capitale e interessi rata(1:n_rate) = qc + interessi(1:n_rate); end    

14. Data  una  serie  di  misurazioni  i  cui  valori  misurati  sono  contenuti  in  un  vettore  x  e  i  relativi  pesi  sono  contenuti  in  un  vettore  w  (delle  stesse  dimensioni  di  x),  la  media  pesata  si  calcola  come  segue:      

 

Si  risponda  ai  seguenti  quesiti  utilizzando  il  linguaggio  MATLAB.    

• Scrivere   una   funzione   mediaPesata   avente   come   argomenti   i   vettori   x   e   w   e   come    risultato  la  media  pesata.      

• Scrivere  una  funzione  mediaPesataSpeciale  con  parametri  analoghi  alla    precedente,  ma  che  calcoli  la  media  pesata  considerando  come  zeri  i  pesi  relativi    alle  misurazioni  con  il  valore  minimo  e  il  valore  massimo.      

• Si  consideri  una  matrice  Z  di  dimensione  2xN  precedentemente  definita  in  cui  le    colonne  rappresentano   le  N  misurazioni,   la   prima   riga   contiene   i   valori   di   ogni  misurazione   e   la  seconda  riga  i  relativi  pesi.  Si  scriva  uno  script  per  trovare  gli  indici  delle  misurazioni  con  valore  compreso  tra  la  media  pesata  e  la  media  pesata  speciale  (estremi  inclusi).      

Soluzione  

% punto 1 function r = mediaPesata(x,w) r = sum(x.*w)/sum(w);  

% punto 2 function r = mediaPesataSpeciale(x,w) % Creazione di un vettore logico che contiene true in corrispondenza % del valore minimo selmin = (min(x) == x); % Creazione di un vettore logico che contiene true in corrispondenza % del valore massimo selmax = (max(x) == x); % Metto a 0 il peso delle celle che contrengono il valore minimo o % quello massimo

x̄ =w1 ⇤ x1 + w2 ⇤ x2 + · · ·+ wn ⇤ xn

w1 + w2 + · · ·+ wn

Corso  di  Informatica  B/C  2014-­‐15   2-­‐40  

w(selmin | selmax)=0; % Calcolo la media usando la funzione sviluppata al punto 1. % Avendo messo a 0 i pesi delle celle che non interessano sto % efffettivamente calcolando la media richiesta al punto 2. r = mediaPesata(x,w);  

 

% punto 3 x = Z(1,:); % Selezione valore misurazioni w = Z(2,:); % Selezione pesi misurazioni mp = mediaPesata(x,w); mps = mediaPesataSpeciale(x,w); if mp <= mps % Selezione delle celle che hanno una misurazione compresa tra % media pesata e media pesata speciale sel = x >= mp & x <= mps; else % Selezione delle celle che hanno una misurazione compresa tra % media pesata speciale e media pesata (l'inverso del punto % precedente) sel = x >= mps & x <= mp; end % Selezione l'indice/posizione delle celle che soddisfano una delle %due situazioni analizzate nei passi precedenti find(sel)  

15. Si  scriva   in   linguaggio  MATLAB  una  funzione  controllaMultipli   che  prende   in   ingresso  una  matrice  M  di  numeri  interi  strettamente  maggiori  di  zero  e  un  numero  intero  positivo  n,  e  restituisce   al   programma   chiamante  un   vettore   colonna  V   avente   lo   stesso  numero  di   righe  della   matrice   M.   La   funzione   determina,   per   ogni   riga   della   matrice   M,   qual   è   il   massimo  numero  di  valori  multipli  di  n  che  compaiono  consecutivamente  in  colonne  adiacenti  della  riga  della  matrice  M   e   assegna   tale   numero   alla   posizione   corrispondente   in   V.  Di   conseguenza,  l’i-­‐esimo  elemento  del  vettore  V  conterrà  il  massimo  numero  di  valori  multipli  di  n  consecutivi  nell’i-­‐esima  riga  della  matrice  M.      

Ad  esempio:  

 

 

 

La   funzione   restituisce   questo   particolare   vettore   V   perché   nella   prima   riga   di  M   individua  come  multipli  di  3  tre  valori  (12,  21,  6),  di  cui  due  (21  e  6)  sono  consecutivi,  nella  seconda  riga  

M =

2

6666664

12 19 4 21 69 18 6 5 183 11 9 3 911 12 5 6 413 1 4 23 17 12 4 9 18

3

7777775M =

2

6666664

12 19 4 21 69 18 6 5 183 11 9 3 911 12 5 6 413 1 4 23 17 12 4 9 18

3

7777775V =

2

6666664

233102

3

7777775n = 3

Corso  di  Informatica  B/C  2014-­‐15   2-­‐41  

individua  come  multipli  di  3  quattro  valori  (9,  18,  6,  18),  di  cui  tre  (9,  18,  6)  sono  consecutivi,  e  cosi  via  fino  all’ultima  riga.  Per  determinare  se  un  valore  è  multiplo  di  un  altro  si  può  utilizzare  la   funzione  mod   che   restituisce   il   resto   della   divisione   intera   tra   due   numeri   (per   esempio,  mod(5,  2)  restituisce  1).      

Si  scriva,  inoltre,  uno  script  che  crei  una  matrice  con  i  valori  dell’esempio  e  chiami  la  funzione  controllaMultipli  passando  come  parametro  la  matrice  creata  e  il  valore  3.  Si  faccia  in  modo  che  il risultato  ottenuto  venga  stampato  a  schermo.  

Soluzione  

controllaMultipli.m  -­‐  function  

function V = controllaMultipli( M , n ) [nRighe, nColonne] = size(M); V = zeros(nRighe,1); for riga = 1:1:nRighe conta = 0; for colonna = 1:1:nColonne if mod(M(riga,colonna),n) == 0 conta = conta + 1; else conta = 0; end V(riga) = max([V(riga),conta]); end end end  

script  

M = [12 19 4 21 6; 9 18 6 5 18; 3 11 9 3 9; 11 12 5 6 4; 13 1 4 23 1; 7 12 4 9 18]; controllaMultipli(M,3)  

   

Corso  di  Informatica  B/C  2014-­‐15   3-­‐42  

Chapter  3 Ricorsione    

1. Si   implementi   una   versione   ricorsiva   dell’algoritmo   di   Euclide   per   il   calcolo   del   Minimo  Comune  Divisore  (MCD)  di  due  numeri  interi,  considerando  le  seguienti  relazioni:  • se  m  =  n,  MCD(m,n)  =  m                        (caso  base)  • se  m  >  n,  MCD(m,n)  =  MCD(m-­‐n,  n)    (ricorsione)  • se  m  <  n,  MCD(m,n)  =  MCD(m,  n-­‐m)    (ricorsione)  

Soluzione  

mcd.m  -­‐  funzione  

function [M] = mcd(m, n, passo) % la variabile "passo" non e` parte della soluzione. if m == n M = m; else if m > n M = mcd(m-n, n, passo+1); else M = mcd(m, n-m, passo+1); end end % ----------------------------------------------------------- % Da qui in poi il codice non fa parte della soluzione % ----------------------------------------------------------- % % Questo codice verra` eseguito solo quando si arrivera` al caso base, % quindi quando "passo" assumera` come valore il numero di passi di ricorsione. % % stampo "passi volte" il carattere TAB per "visualizzare" a che punto % della ricorsione mi trovo for ii = 1:passo fprintf('\t'); end % stampo l'invocazione corrente fprintf('|--> mcd: m = %d, n = %d, passo = %d\n', m, n, passo); % ----------------------------------------------------------- end

 

   

Corso  di  Informatica  B/C  2014-­‐15   3-­‐43  

2. Scrivere   una   funzione   che   verifichi   iterativamente   se   una   stringa   è   palindroma.   Scrivere   poi  una  funzione  che  implementi  la  stessa  funzionalità  in  modo  ricorsivo.  

Soluzione  

palindroma_iterativa.m  -­‐  funzione  

function [res] = palindroma_iterativa(par) res = 1; for ii = 1:length(par)/2 % questa linea non fa parte della soluzione fprintf('passo = %d: %c =?= %c\n',ii,par(ii),par(end-ii+1)); if par(ii) ~= par(end - ii + 1) res = 0; return; end end

 

palindroma_ricorsiva.m  –  funzione  

function [res] = palindroma_ricorsiva(parola) % Caso base: stringhe di un carattere (o vuote sono palindrome) if length(parola) < 2 res = 1; else % controllo se gli estremi sono uguali % if parola(1) == parola(end) % Passo ricorsione: richiama palindroma_ricorsiva % su parola(2, end-1) res = palindroma_ricorsiva(parola(2:end-1)); % da qui, l'esecuzione e` bloccata fino a che la funzione % precedente non ritorna else res = 0; end end

 

 

 

 

 

 

Corso  di  Informatica  B/C  2014-­‐15   3-­‐44  

main.m  –  script  per  provare  le  funzioni  

% parola palindroma R = 'abbAbba'; % parola non palindroma P = 'abbiibaia'; fprintf('-----------------------------------------------------\n'); % invocazione funzione iterativa palindroma_iterativa(R); fprintf('-----------------------------------------------------\n'); palindroma_iterativa(P); fprintf('-----------------------------------------------------\n'); % invocazione funzione ricorsiva palindroma_ricorsiva(R, 1); fprintf('-----------------------------------------------------\n');  

 

Corso  di  Informatica  B/C  2014-­‐15   3-­‐45  

3. Si  implementi  una  funzione  iterativa  (e    una  sua  versione  ricorsiva)  per  tradurre  i  caratteri  di  una  stringa  da  minuscoli  a  maiuscoli.  Assumere  che  la  funzione  riceva  in  ingresso  una  stringa  di  caratteri  minuscoli.  La   traduzione   viene   effettuata   semplicemente   sottraendo   32   al   carattere   da   tradurre,   e  applicando  char().    

Ad  esempio:  

>  char('a'-­‐32)  

ans  =  'A'  

Soluzione  

maiuscola_iterativa.m  -­‐  funzione  

function S = maiuscola_iterativa(s) for ii = 1:length(s) S(ii) = char(s(ii) - 32); % la linea successiva non fa parte della soluzione fprintf('passo iterativo = %d: %c -> %c\n',ii,s(ii),S(ii)); end end % Nota: % anche se in questo esercizio era richiesta esplicitamente una % versione % iterativa, sappiate che è possibile realizzare la stessa % operazione % con una sola chiamata a char(s-32), dove "s" è la stringa.

 

maiuscola_ricorsiva.m  -­‐  funzione    

function S = maiuscola_ricorsiva(s, passo) % % Passo è una variabile di supporto, per chiarire il concetto % di ricorsione; in particolare indica il passo ricorsivo % corrente (e.g., primo, secondo, terzo). % % Caso base: stringa di un carattere if length(s) < 2 S = [char(s(1) - 32)]; else S = [char(s(1) - 32) maiuscola_ricorsiva(s(2:end), passo+1)]; end

Corso  di  Informatica  B/C  2014-­‐15   3-­‐46  

% Alternativamente: % ---------------- % % Caso base: stringa vuota % if ~length(s) % S = []; % else % ...idem... % end % ----------------------------------------------------------- % da qui in poi il codice non fa parte della soluzione % ----------------------------------------------------------- for ii = 1:passo fprintf(' '); end fprintf('|--> maiuscola_ricorsiva(%s, %d)\n', s, passo); % ----------------------------------------------------------- % fine

 

main.m  -­‐  script  per  provare  le  funzioni  

s = 'ciaocomestai'; fprintf('-----------------------------------------------------\n'); S = maiuscola_iterativa(s) fprintf('-----------------------------------------------------\n'); S = maiuscola_ricorsiva(s, 1) fprintf('-----------------------------------------------------\n');    

   

Corso  di  Informatica  B/C  2014-­‐15   3-­‐47  

4. Dato  un  numero  reale  positivo  si  richiede  di  scrivere  una  funzione  iterativa  e  la  sua  versione  ricorsiva  per  tradurlo  in  notazione  scientifica,  ovvero  in  un  numero  reale  e  una  potenza  di  10.  Per  esempio:    12345.1  diventa  1.23451  e  10^4.  

Soluzione  

notazione_scientifica.m  –  funzione  

function [num, exp] = notazione_scientifica(n) if n <=10 num = n; exp = 0; else c = 0; while n >= 10 n = n/10; % dividiamo il numero per 10 c = c + 1; end num = n; exp = c; end

 

notazione_scientifica_ricorsivia.m  –  funzione  

function [num, exp] = notazione_scientifica_ricorsiva(n,c) % quando si richiama questa funzione bisogna passarle c = 0 if n <=10 num = n; exp = c; else if n >=10 n = n/10; [num, exp] = notazione_scientifica_ricorsiva(n, c+1) end end    

Corso  di  Informatica  B/C  2014-­‐15   3-­‐48  

5. Un  metodo  per  calcolare  il  valore  approssimato  x(n)  della  radice  quadrata  di  un  numero  reale  non  negativo  Z,  detto  metodo  babilonese,  utilizza  la  seguente  relazione  ricorsiva:  

 

con    

Dove   n   è   un   intero   non   negativo   arbitrario,   mentre   x(n)   è   l'approssimazione   della   radice  quadrata  di  z.    

Per  esempio,  se  si  vuole  calcolare  la  radice  quadrata  approssimata  di  Z  =  2  e  si  sceglie  di  farlo  con   n   =   3,   il   valore   di   x(n=3)   ottenuto   con   il   metodo   babilonese   è   1.4142.   Variando   n   si  ottengono  diverse  approssimazioni  della  radice  di  z,  ma  varia  anche  il  numero  di  ricorsioni  per  ottenere  tali  approssimazioni.  

L'errore   di   approssimazione   si   ottiene   con:   e   decresce   al  crescere  di  n.  

• Scrivere  una  funzione  ricorsiva  sqrt1(z,n)  che  restituisca  un'approssimazione  della  radice  quadrata  ed  il  relativo  errore.  Quando  n  =  0  si  assuma  che  l'errore  sia  pari  a  inf.  

• Scrivere  una   funzione  sqrt2(z,err)   che,  utilizzando   la   funzione   sqrt1,   restituisca  un  valore  approssimato  della   radice  quadrata  di   z   con  un  errore  di   approssimazione  non  superiore  al  valore  err  fornito  come  parametro.  

Soluzione  

sqrt1.m  -­‐  funzione  

function [r err] = sqrt1(z, n) if n == 0 % caso base err = inf; r = 1; elseif n > 0 % ricorsione [r_temp err_temp] = sqrt1(z, n-1); % passo ricorsivo % calcolo di x(n) r = (r_temp + z / r_temp)/2; % x(n) = (x(n-1)+z/x(n-1))/2 % dove x(n-1) = r_temp % calcolo di err(n) err = abs(r - r_temp); % scostamento end

 

 

 

 

x(n) =1

2⇥ (x(n� 1) +

Z

x(n� 1))

x(0) = 1

err(n) = |x(n)� x(n� 1)|

Corso  di  Informatica  B/C  2014-­‐15   3-­‐49  

sqrt2.m  -­‐  funzione  

function r = sqrt2(z, err) n = 0; err_temp = inf; % errore inizialmente infinito % cerco n tale che err_temp <= err while err_temp > err % condizione negata n = n + 1; [r err_temp] = sqrt1(z, n); end  

6. Si  dica  cosa  calcola  la  seguente  funzione  ricorsiva:  a. Quando si passano i parametri 7 e 8.  b. In generale.  

 function z = mistero(x) if x >= 1 z = mod(x,2) + 10*mistero(floor(x/2)); else z = 0; end Soluzione  

La  figura  qui  sotto  mostra  come  avvengono  le  chiamate  ricorsive.  In  particolare  viene  mostrato  in  ogni  

blocco  l'ambiente  locale  di  esecuzione  associato  ad  ogni  chiamata.

1. mistero(7)=111,  mistero(8)=1000      

2. mistero(x)  calcola  un  valore  numerico  in  base  10  la  cui  sequenza  di  cifre    può  essere  interpretata  come  rappresentazione  del  numero  naturale  x  nel  sistema  binario.        

Corso  di  Informatica  B/C  2014-­‐15   3-­‐50  

7. Si  spieghi  cosa  fa   la  seguente  funzione,   fornendo  *anche*  degli  esempi  di  output  a  fronte  di  alcuni  esempi  di  input  

Soluzione  

function r = misteriosa(array) k = size(array, 2); % come se fosse length(array) % assumendo vettori riga if (k == 1) % caso base 1: se ha una sola cella r = 1; % ritorno 1 elseif (k == 2) % caso base 2: se invece ha due celle if (array(1) + array(2) == 10)

% se la prima e la seconda cella == 10 r = 1; % ritorna 1 else r = 0; % altrimenti ritorna 0 end else % se invece ha > 2 celle if (array(1) + array(k) == 10)

% se la prima + ultima cella == 10 r = misteriosa(array(2:k-1));

% passo ricorsivo sul vettore 2:k-1 else r = 0; % ritorna 0 end end % controlla se un vettore di interi, scansito dall'esterno verso % l'interno ha % tutte celle opposte che sommano a 10: se sì ritorna 1,altrimenti 0. misteriosa([1 9 3 2 8 7 1 9]) % ci aspettiamo 1 misteriosa([1 9 3 2 8 7 2]) % ci aspettiamo 0 misteriosa([1]) % 1 misteriosa([1 2]) % 0

function r = misteriosa(array) k = size(array, 2); if (k == 1) r = 1; elseif (k == 2) if (array(1) + array(2) == 10) r = 1; else r = 0; end else if (array(1) + array(k) == 10) r = misteriosa(array(2:k-1)); else r = 0; end end

Corso  di  Informatica  B/C  2014-­‐15   3-­‐51  

8.  (TdE)  Si  consideri  la  seguente  funzione:    

function [ris] = s(n) if n<1 ris = -1; elseif n>=1 && n<=4 %* ris = n; %* else ris = s(n-2)*s(n-4); end

e  lo  script  che  la  richiama:  

% script s1 che richiama s for x = 1:8 fprintf('%d, ', s(x)); end

• Quali risultati vengono stampati a video? Si supponga di rimuovere le righe di codice evidenziate da un asterisco:

• La terminazione della ricorsione è ancora garantita per ogni valore dell’argomento n? In caso affermativo giustificare brevemente la risposta, in caso negativo riportare almeno un esempio di argomento in cui la ricorsione non termina.

• Con la modifica apportata quali risultati vengono stampati a video?

Si forniscano opportune giustificazioni per tutte le risposte.

Soluzione  

Soluzione

• Per  x  compreso  tra  1  ed  8  il  programma  calcola  e  stampa  la  seguente  sequenza  di  numeri  1,  2,  3,  4,  3,  8,  9,  32.  Infatti:    s(1)  =  1    s(2)  =  2      s(3)  =  3    s(4)  =  4    s(5)  =  s(3)*s(1)  =  3*1  =  3    s(6)  =  s(4)*s(2)  =  4*2  =  8    s(7)  =  s(5)*s(3)  =  3*3  =  9      s(8)  =  s(6)*s(4)  =  8*4  =  32  

• La  ricorsione  termina  sempre,  dato  che  per  qualsiasi  argomento  la  funzione  viene  richiamata  su  argomenti  sempre  minori  fino  a  raggiungere  il  caso  base:  un  argomento  minore  o  uguale  a  zero    

 • La  nuova  sequenza  è  1,  1,  -­‐1,  -­‐1,  -­‐1,  -­‐1,  1,  1  .  Infatti:    

s(1)  =  s(-­‐1)*s(-­‐3)  =  (-­‐1)*(-­‐1)  =  1    s(2)  =  s(0)*s(-­‐2)  =  (-­‐1)*(-­‐1)  =  1      

Corso  di  Informatica  B/C  2014-­‐15   3-­‐52  

s(3)  =  s(1)*s(-­‐1)  =  (1)*(-­‐1)  =  -­‐1    s(4)  =  s(2)*s(0)  =  (1)*(-­‐1)  =  -­‐1    s(5)  =  s(3)*s(1)  =  (-­‐1)*(1)  =  -­‐1    s(6)  =  s(4)*s(2)  =  (-­‐1)*(1)  =  -­‐1    s(7)  =  s(5)*s(3)  =  (-­‐1)*(-­‐1)  =  1    s(8)  =  s(6)*s(4)  =  (-­‐1)*(-­‐1)  =  1    

9. (TdE) Si  considerino  la  funzione  e  lo  script  seguenti:  

function†[r]†=†MiaFunz(a,†b) if b == 0 r=1; else r = a * MiaFunz(a, b-1); end;  

%script che chiama MiaFunz x=2; for y = 0:1:4 r = MiaFunz(x,y) end

• Descrivere  brevemente  quale  sia  la  funzione  matematica  calcolata  dalla  funzione  MiaFunz.  Giustificare  la  risposta.          

• Quali   risultati   vengono   stampati   a   video?   Non   è   necessario   calcolare   i   valori   numerici  esatti,   ma   è   sufficiente   riportare   le   espressioni   aritmetiche   necessarie   per   calcolarli.  Giustificare  la  risposta.    

Soluzione  

La  funzione  matematica  calcolata  dalla  funzione  MiaFunz(a,b)  è  ab,  sotto  l'ipotesi  che  b≥0  I  risultati  stampati  a  video  sono:    20=1  

21=2  

22=4  

23=8  

24=16      

Corso  di  Informatica  B/C  2014-­‐15   3-­‐53  

10. Si   consideri   una  matrice   triangolare   T,   rappresentante   il   famoso   triangolo   di   Tartaglia,   i   cui  valori,  identificati  dal  loro  numero  di  riga  e  di  colonna  a>b,  sono  definiti  nel  seguente  modo:    

T(a,1) = 1 T(a,a) = 1 T(a,b)=T(a-1,b-1)+T(a-1,b) Ad  esempio,  le  prime  5  righe  della  matrice  triangolare  T  sono  le  seguenti:    

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

Si   scriva   una   funzione   ricorsiva   che,   utiizzando   la   definizione   sopra,   permetta   di   calcolare   il  valore  di  un  generico  elemento  della  matrice  T.    

Soluzione  

La  soluzione  a  questo  quesito  puo'  essere  determinata  facilmente  in  quanto  dalla  definizione  e'  possibile  ricavare  il  caso  base  e  il  caso  ricorsivo  della  ricorsione.    

Rappresentiamo  T   come  una   funzione   che  ha   come  argomenti   la   riga   e   la   colonna  e   come   risultato   il  valore  contenuto  nella  matrice  (che  dobbiamo  calcolare).    

CASO BASE: T(a,1)=1 e T(a,a)=1

Questo   caso   base   ci   dice   che   se   il   secondo   parametro   della   funzione   e'   uguale   a   1,   oppure   uguale   al  primo  parametro,  il  risultato  sara'  1  e  si  termina  la  ricorsione.    

CASO RICORSIVO: T(a,b)=T(a-1,b-1)+T(a-1,b)

Questo  caso  ricorsivo  ci  dice  che  in  tutti  gli  altri  casi,   il  risultato  si  calcola  chiamando  ricorsivamente  la  funzione.    

function ris = tartaglia(a,b) if b == 1 || a == b ris = 1; else ris = tartaglia(a-1,b-1)+tartaglia(a-1,b); end  

Corso  di  Informatica  B/C  2014-­‐15   3-­‐54  

11. Si  scrivano  in  linguaggio  MATLAB:    • una  funzione  ricorsiva  che  calcoli  il  risultato  della  divisione  intera  a/b.    • una  funzione  ricorsiva  che  calcoli  il  resto  della  divisione  intera  a/b.    • una  funzione  ricorsiva  che  calcoli  sia  il  risultato  sia  il  resto  della  divisione  intera  a/b.    

Suggerimento:    

a/b = 1+(a-b)/b

Soluzione    

Caso  1  

function risultato = divisione(a,b) if a >= b risultato = 1 + divisione(a-b,b); else risultato=0; end

 

Caso  2  

function r = resto(a,b) if a >= b r = resto(a-b,b); else r = a; end    

Caso  3  

function [risultato, resto] = divisioneresto(a,b) if a>=b [risultato1, resto1] = divisioneresto(a-b,b); risultato = risultato1 + 1; resto = resto1; else risultato=0; resto=a; end  

   

Corso  di  Informatica  B/C  2014-­‐15   3-­‐55  

12. Si  scriva  una  funzione  in  MATLAB  che  abbia  come  parametro  di  ingresso  un  vettore  contente  un  insieme  di  valori,  e  stampi  tutte  le  permutazioni  di  tali  valori.    Ad  esempio,  se  i  valori  sono  [1  2  3],  considerando  questo  schema:    

1 2 3 (primo numero) / \ / \ / \ 2 3 1 3 1 2 (possibili secondi numeri) | | | | | | 3 2 3 1 2 1 (possibili terzi numeri)

 

Le permutazioni di [1 2 3] sono:

[1 2 3], [1 3 2], [2 1 3], [2 3 1], [3 1 2], [3 2 1].

Soluzione

Osservando   lo   schema   possiamo   notare   che   abbiamo   bisogno   di   due   informazioni:   1)   i   valori   già  considerati   precedentemente   nelle   permutazioni   (per   non   ripeterli)   e   i   valori   ancora   disponibili   (da  aggiungere).   Questo   fa   sì   che   la   nostra   funzione   ricorsiva   debba   avere   due   parametri   d’ingresso:   1)  l'insieme  dei  valori  già  inseriti  nella  permutazione  e  2)  l'insieme  dei  valori  ancora  da  inserire.  

Poiché'  la  funzione  richiesta  dall'esercizio  ha  un  solo  parametro,  cioè  l'insieme  dei  valori  da  inserire  nella  permutazione,   avremo   bisogno   di   creare   due   funzioni.   La   prima   con   un   solo   parametro   contenente   i  valori  da   inserire,  e   la   seconda  con  due  parametri   contenenti   i   valori   già   inseriti  nella  permutazione  e  quelli  ancora  da  inserire.  

La  prima  funzione  avrà  solo  lo  scopo  di  nascondere  a  chi  la  invoca  che  c’è  un  parametro  in  più.  Questa  funzione  chiamerà  la  seconda  funzione  passando  un  insieme  vuoto  come  valori  già  inseriti,  e  tutti  i  valori  disponibili  come  valori  da  inserire.  

La  funzione  ricorsiva  sarà  strutturata  in  questo  modo:  

CASO  BASE  

L'insieme  dei  valori  da  inserire  è  vuoto:  stampo  semplicemente  i  valori  già  inseriti  (primo  parametro)  e  termino.  

CASO  RICORSIVO  

L'insieme  dei  valori  da  inserire  non  è  vuoto:  scandisco  tutti  i  possibili  valori  ancora  da  inserire  ed  eseguo  un’invocazione  ricorsiva  della  funzione  per  ognuno  di  questi  valori.  In  queste  invocazioni  ricorsive  passo  come  primo  parametro   i   valori   già   inseriti   dal   chiamante,   più  quello   nuovo   che   sto   scandendo.   Come  secondo  parametro  invece  passo  tutti  i  valori  ancora  da  inserire,  eccetto  quello  che  sto  scandendo.  

 

 

 

Corso  di  Informatica  B/C  2014-­‐15   3-­‐56  

Codice  

function p=permutazioni(m) permuta([],m);  

function ris=permuta(p, m) if length(m)>0 for k=1:length(m) permuta([p m(k)], m([1:k-1 k+1:end])); end else p end  

   

Corso  di  Informatica  B/C  2014-­‐15   3-­‐57  

 

13. Il   Sudoku  è  un   gioco  di   logica  nel   quale   al   giocatore   viene  proposta  una  griglia  di   9×9   celle,  ciascuna   delle   quali   può   contenere   un   numero   da   1   a   9,   oppure   essere   vuota;   la   griglia   è  suddivisa  in  9  righe  orizzontali,  nove  colonne  verticali  e  in  9  "sottogriglie",  chiamate  regioni,  di  3×3  celle  contigue.  Scopo  del  gioco  è  quello  di  riempire  le  caselle  bianche  con  numeri  da  1  a  9,  in   modo   tale   che   in   ogni   riga,   colonna   e   regione   siano   presenti   tutte   le   cifre   da   1   a   9   e,  pertanto,  senza  ripetizioni.  L’esempio  sotto  riportato  mostra  una  griglia  Sudoku  corretta.      

 

  Si  vuole  realizzare  un  programma  in  grado  di  verificare  se  una  griglia  assegnata  rispetta  le  regole  del  gioco.    

• Si   implementi   la   funzione   verificaBase,   che   prenda   in   ingresso   una   vettore   riga     La  funzione  restituisca  1  se  il  vettore  v  contiene  tutti  i  numeri  compresi  tra  1  e  9.    

• Si   implementi   la   funzione   verificaRighe,   che   riceva   in   ingresso   una   matrice   9x9  rappresentante   una   soluzione   del   Sudoku     e restituisca   1   se   le   righe   della   matrice  Sudoku  passata  come  parametro  rispettano  le  regole  del  gioco.    

• Si   implementi   la   funzione   verificaColonne,   che   riceva   in   ingresso   una   matrice   9x9  rappresentante  una   soluzione  del   Sudoku     e restituisca   1   se   le   colonne  della  matrice  Sudoku  passata  come  parametro  rispettano  le  regole  del  gioco.    

1   2   3   4   5   6   7   8   9  

4   5   6   7   8   9   1   2   3  

7   8   9   1   2   3   4   5   6  

2   3   4   5   6   7   8   9   1  

5   6   7   8   9   1   2   3   4  

8   9   1   2   3   4   5   6   7  

3   4   5   6   7   8   9   1   2  

6   7   8   9   1   2   3   4   5  

9   1   2   3   4   5   6   7   8  

Corso  di  Informatica  B/C  2014-­‐15   3-­‐58  

• Si   implementi   la   funzione   verificaRegioni,   che   riceva   in   ingresso   una   matrice   9x9  rappresentante  una   soluzione  del   Sudoku     e   restituisca  1   se   le   9   regioni  della  matrice  sudoku  passata  come  parametro  rispettano  le  regole  del  gioco.    

• Si  implementi  infine  la  funzione  verificaSudoku,  ,  che  riceva  in  ingresso  una  matrice  9x9  rappresentante  una  soluzione  del  Sudoku    e  restituisca  1  se   la  matrice  sudoku  passata  come  parametro,  rispetta  tutte  le  regole  del  gioco    

Soluzione  

verificaBase.m    -­‐  funzione  

function [ ris ] = verificaBase( v ) ris = 0;

l = length(v);

for ii =1:l

if isempty(find(v==ii))

return ;

end

end

ris =1;

 

   

Corso  di  Informatica  B/C  2014-­‐15   3-­‐59  

verificaRighe.m  –  funzione  

function [ ris ] = verificaRighe( sudoku ) [r c] = size(sudoku);

���for ii=1:r

riga = sudoku(ii ,:); ���

ris = verificaBase(riga);

if ris == 0

return

end

end

 

verificaColonne.m  –  funzione  

function [ ris ] = verificaColonne ( sudoku) ris = verificaRighe(sudoku');  

   

Corso  di  Informatica  B/C  2014-­‐15   3-­‐60  

verificaRegioni.m  –  funzione  

function [ ris ] = verificaRegioni( sudoku )

[r c] = size(sudoku); ���

for ii = 1:3:r-2

for jj =1:3:c ���-2

subM=sudoku(ii:ii+2, jj:jj+2);

ris = verificaBase (subM(:) ) ;

if ris == 0

return

end

end

end

 

verificaSudoku.m  –  funzione  

function [ ris ] = verificaSudoku( sudoku)

ris = verificaRighe (sudoku) ;

���if ris==0

disp('La matrice viola le regole di riga');

return

end

ris = verificaColonne (sudoku) ;

Corso  di  Informatica  B/C  2014-­‐15   3-­‐61  

if ris==0

disp ('La matrice viola le regole di colonna') ;

return

end

ris = verificaRegioni (sudoku) ;

if ris==0

disp('La matrice viola le regole di regione');

return

end

disp('Matrice OK!');

   

Corso  di  Informatica  B/C  2014-­‐15   4-­‐62  

 

Chapter  4 Accesso  ai  file  

1. Un'agenzia   di   viaggi   possiede   un   proprio   database   di   destinazioni   e   di   acquisti   effettuati.   Il  database  e'  composto  da  due  file:  il  primo  ‘dest.dat’  in  ogni  riga  ha  il  nome  della  destinazione  e   il   prezzo;   il   secondo   ‘acquisti.dat’   in   ogni   riga   ha   il   nome   del   cliente   e   il   nome   della  destinazione  dell'acquisto  effettuato.    

• Si  scriva  uno  script  che  carichi  il  database.      • Si  stampi  il  fatturato  generato  da  ogni  destinazione.  

Soluzione  

% parte 1 [dest_nome, dest_costo] = textread('dest.dat','%s %f') [acquisti_nome, acquisti_dest]= textread('acquisti.dat','%s %s') % parte 2 for ii=1:size(dest_nome) fatturato=0; for jj=1:size(acquisti_dest) if strcmp(acquisti_dest(jj),dest_nome(ii)) % strcmp restituisce 1 se sono uguali, 0 se sono diversi % In C e' il contrario!!! fatturato = fatturato + dest_costo(ii); end end disp(['Fatturato per ', est_nome(ii), ': ', num2str(fatturato)]); end  

   

Corso  di  Informatica  B/C  2014-­‐15   5-­‐63  

Chapter  5 Diagrammi  1. Si  disegni  la  superficie  del  paraboloide  iperbolico  dato  dalla  seguente  equazione:  

z=x.^2-y.^2 per valori di x e y nell'intervallo [-5,+5]. Impostare titoli ed etichette.

 Soluzione

Assegno innanzitutto  (come  nei  grafici  a  due  dimensioni)  vari  valori  nell'intervallo  da  -­‐5  a  +5  (separati  da  micro  intervalli  di  dimensione  opportuna)  alle  variabili  x  e  y.  Più  piccoli  sono  tali  intervalli  e  più  definito  sarà  il  grafico.  Dopodiché'  creo  con  la  funzione  meshgrid le  matrici  xx e  yy contenenti  la  prima  i  valori  di  x  ripetuti  length(y)  volte,  la  seconda  i  valori  di  y'  ripetuti  length(x)  volte.  La  coppia  di  queste  matrici  identifica  la  griglia  rettangolare  che  sarà  utilizzata  per  modellare  la  superficie  identificata  da  zz (più  piccoli  sono  gli  intervalli  di  x  e  y  e  più  fitta  sarà  la  griglia).  La  matrice  zz si  calcola  da  xx  e  yy  utilizzando  direttamente  l'equazione  della  funzione  a  due  variabili  da  rappresentare  (zz=xx2-yy2  in  questo  caso).  Infine,  le  tre  matrici  ottenute  (xx,yy,zz)  saranno  i  parametri  dell'istruzione  mesh che  disegnerà  il  grafico.

x=-5:0.05:5; y=x; [xx yy]=meshgrid(x,y); zz=xx.^2-yy.^2; mesh(xx,yy,zz); title('Paraboloide iperbolico') xlabel('Asse x') ylabel('Asse y') zlabel('Asse z') Risultato