Esercizi proposti Problema 1: Calcolare il numero di occorrenze di un valore dato in una sequenza data Stato iniziale: {dim K, val V, c[0] V 0,..., c[k-1] V K-1 } K > 0 Stato finale: {occ #{ j j 2 [0,K-1] ^ V j =V}} Problema 2: Calcolare contemporaneamente il massimo e il minimo di una sequenza data di interi Stato iniziale: {dim K, c[0] V 0,..., c[k-1] V K-1 } con K > 0 Stato finale: {massimo max({v 0,...,V K-1 }), minimo min({v 0,...,V K-1 })} Problema 3: Calcolare il numero di occorrenze del valore massimo in una sequenza di interi Stato iniziale:? Stato finale:? Problema 4: Calcolare la media di una sequenza data di interi Stato iniziale:? Stato finale:? C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 20
Soluzione problema 1: Stato iniziale: {dim K, val V, c[0] V 0,..., c[k-1] V K-1 } K > 0 Stato finale: {occ #{ j j 2 [0,K-1] ^ V j =V}} occ = 0; i = 0; while (i <= dim-1) { if (c[i] == val) occ = occ + 1; i = i + 1; } Ad ogni iterazione del ciclo vale la proprietà: occ = #{ j j 2 [0,i-1] ^ c[j] = val} C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 21
Variazione problema 1: Stato iniziale: {dim K, val V, c[0] V 0,..., c[k-1] V K-1 } K > 0 Stato finale: {occ #{ j j 2 [0,K-1] ^ V j =V}, pos min(j) V j =V} occ = 0; pos = -1; i = 0; while (i <= dim-1) { if (c[i] == val) {occ = occ + 1; if (occ == 1) pos = i;} i = i + 1; } C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 22
Soluzione alternativa alla variazione problema 1: Dato che la sequenza è memorizzata, posso scorrerla anche a partire dal fondo. Ad ogni iterazione aggiorno la posizione dell occorrenza corrente (scandendo da destra a sinistra) del valore cercato: alla fine rimarrà la posizione dell ultima occorrenza (sempre scandendo da destra a sinistra), che corrisponde alla prima (scandendo da sinistra a destra). occ = 0; pos = -1; i = dim-1; while (i >= 0) { if (c[i] == val) {occ = occ + 1; pos = i;} i = i + 1; } Se dovessi invece elaborare una sequenza di dati in ingresso senza prima memorizzarli, dovrei usare la prima soluzione. C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 23
Soluzione problema 2 Stato iniziale: {dim K, c[0] V 0,..., c[k-1] V K-1 } con K > 0 Stato finale: {massimo max({v 0,...,V K-1 }), minimo min({v 0,...,V K-1 })} I Come calcolare il massimo è ormai noto, e calcolare il minimo è del tutto analogo (basta invertire il confronto). Per calcolare entrambi possiamo procedere nel modo seguente. I massimo = c[0]; minimo = c[0]; i = 1; while (i <= dim-1) { if (c[i] > massimo) massimo = c[i]; if (c[i] < minimo) minimo = c[i]; i = i + 1; } calcolo del massimo calcolo del minimo C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 24
I Ottimizzando: massimo = c[0]; minimo = c[0]; i = 1; while (i <= dim-1) { if (c[i] > massimo) massimo = c[i]; if (c[i] < minimo) minimo = c[i]; i = i + 1; } calcolo del massimo calcolo del minimo C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 25
Soluzione problema 3 Stato iniziale: dim K, c[0] V 0,..., c[k-1] V K-1 Stato finale: occ #{j j 2 [0,K-1] ^ V j = max{v 0,...,V K-1 }} I Un algoritmo ingenuo: I Calcoliamo il valore massimo come nel problema 2 I Scandiamo nuovamente la sequenza per contare il numero di occorrenze del massimo I Comporta una duplice scansione della sequenza I Un algoritmo che comporta una singola scansione si ottiene adattando quello visto per il calcolo del massimo C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 26
massimo = c[0]; i = 1; occ = 1; while (i < = dim-1) { if (c[i] > massimo) { massimo = c[i]; occ = 1; } if (c[i] == massimo) occ = occ + 1; ; i = i + 1; } C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 27
Soluzione problema 4: Stato iniziale: {dim K, c[0] V 0,..., c[k-1] V K-1 } con K > 0 K-1 P Stato finale: {somma V j,media ( K-1 P V j )/K } j=0 media = 0; somma = c[0]; i = 1; while (i <= dim -1) { somma = somma + c[i]; i = i + 1; } media = somma/dim; Ad ogni iterazione del ciclo vale la proprietà: somma = X 0apple japple i-1 c[j] j=0 C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 28
Schemi di programma: ricerca e verifica I Molti problemi riguardano la ricerca di elementi in intervalli o la verifica di proprietà. I Sviluppiamo schemi di programma (dimostrabilmente corretti) che realizzano la ricerca e la verifica. I La soluzione di problemi concreti consiste poi nella sostituzione di alcuni parametri degli schemi con valori specifici dei problemi in esame. I Distinguiamo due tipi di ricerca: ricerca certa e ricerca incerta. I I ricerca certa: si vuole determinare il minimo elemento di un intervallo [a,b) per il quale vale una certa proprietà P, sapendo che almeno un elemento dell intervallo soddisfa P. ricerca incerta: si vuole determinare, se esiste, il minimo elemento di un intervallo [a,b) per il quale vale una certa proprietà P. C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 29
Ricerca certa I Intervallo di ricerca: [a,b) I Proprietà: P( ) I Ipotesi di certezza: 9 i 2 [a,b). P(i) I Stato finale: x=min { i2 [a,b) P(i)}. I Lo schema generale per risolvere il problema è il seguente: int x; x=a; while (!P(x)) x=x+1; I Nota: l estremo destro dell intervallo non serve. I Si assume che la proprietà P sia esprimibile nel linguaggio. C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 30
Ricerca certa: esempio 1 I Calcolare la radice intera di un numero naturale. I Si può esprimere come problema di ricerca certa: b p Nc= min x2 [0,N+1) x 2 apple N < (x+1) 2 I Dunque l estremo sinistro dell intervallo di ricerca, a nello schema, in questo caso è 0, mentre l estremo destro, b nello schema, è N. I Infine la proprietà P(x) dello schema è N < (x+1) 2 int x; x=0; while ((x+1)*(x+1) <= N) x=x+1; C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 31
Ricerca certa: esempio 2 I Determinare la posizione della prima occorrenza di un dato elemento in un array, sapendo che tale elemento vi occorre almeno una volta. I Indichiamo con vet l array e con DIM la sua dimensione I Vogliamo determinare: x=mini2 [0,DIM) vet[i] = el I Possiamo istanziare lo schema come segue: int x; x=0; while (vet[x]!=el) x=x+1; C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 32
Ricerca incerta I Si vuole determinare, se esiste, ilminimoelementodiun intervallo [a,b) per il quale vale una certa proprietà P. I Perché lo schema di ricerca certa non va bene? x=a; while (!P(x)) x=x+1; I Se l elemento non c è si vanno ad esaminare valori di x che sono al di fuori dell intervallo di ricerca e per i quali la la proprietà P potrebbe addirittura non essere definita (errore a tempo di esecuzione). Esempio: Nel caso della ricerca incerta di un elemento in un array di dimensione DIM si andrebbero ad esaminare elementi del tipo vet[x] con x >= DIM. I Abbiamo bisogno di modificare lo schema in modo che l analisi degli elementi avvenga solo all interno dell intervallo di ricerca e che la ricerca venga interrotta una volta esaurito l intervallo (e non individuato alcun elemento). C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 33
Ricerca incerta I Intervallo di ricerca: [a,b) I Proprietà: P( ) I Stato finale: x=min i2 [a,b) P(i) dobbiamo stabilire se min b 9i 2 [a, b) :P(i) =) dobbiamo stabilire quale valore calcolare se nessun elemento dell intervallo soddisfa P: una buona scelta è il valore b, che sicuramente non fa parte dell intervallo. C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 34
Ricerca incerta I Utilizziamo una variabile booleana trovato (oppure esiste) che fa da sentinella =) impone l uscita dal ciclo non appena si individua un elemento che soddisfa la proprietà I in congiunzione con la sentinella, la guardia del ciclo assicura che l intervallo di ricerca non sia esaurito int trovato = FALSE; /* inizialmente false */ int x=a; while (x<b &&!trovato) if (P(x)) trovato = TRUE; /*x soddisfa P */ x=x+1; I Si suppone che le costanti TRUE e FALSE siano state definite opportunamente, ad esempio mediante le direttive #define FALSE 0 #define TRUE 1 C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 35
All uscita dal ciclo abbiamo due possibilità: 1. trovato ^ x 2 [a,b) ^ x=min i2 [a,b) P(i) I x è l i n d i c e c e r c a t o I il valore di verità di trovato è TRUE 2. trovato ^ x=b ^8 i2 [a,b). P(i) I nessun elemento nell intervallo di ricerca soddisfa P I il valore di x è b (fuori dell intervallo) I il valore di verità di trovato è FALSE C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 36
Ricerca incerta: esempio I Determinare la prima occorrenza di un elemento in un array. I È un problema di ricerca incerta: min x2 [0,DIM) vet[x] = el min DIM int trovato = FALSE; int x=0; while ( x<dim &&!trovato) if (vet[x]==el) trovato = TRUE; x=x+1; C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 37
I Vi sono situazioni in cui la proprietà P della ricerca (certa o incerta) non è direttamente esprimibile nel linguaggio. Esempio: Determinare (se c è) la posizione del primo elemento di un array di interi che è uguale alla somma degli elementi che lo precedono. I Si tratta di un problema di ricerca incerta in cui 1. l intervallo [a,b] è [0,DIM] 2. la proprietà P(x) è vet[x]= x P 1 vet[j] j=0 int trovato = FALSE; int x=0; while (x<dim &&!trovato) if (vet[x]== x P 1 vet[j]) j=0 trovato = TRUE; x=x+1; C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 38
I In questi casi si utilizza la seguente tecnica: 1. si rimpiazzano le espressioni critiche con variabili 2. si impone l uguaglianza tra le variabili introdotte in questo modo e le corrispondenti espressioni critiche, aggiungendo quanto necessario al corpo del ciclo per mantenere vere tali uguaglianze I Nell esempio: int trovato = FALSE; int x=0; int sommaprecedenti = 0; while (x<dim &&!trovato) if (vet[x]==sommaprecedenti) trovato = TRUE; { sommaprecedenti = sommaprecedenti + vet[x]; x=x+1; } C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 39
Verifica di una proprietà I Vogliamo verificare che tutti gli elementi di un intervallo soddisfano una certa proprietà P. 8i 2 [a, b) :P(i) 1. Facciamo una ricerca incerta del minimo elemento dell intervallo per il quale non vale la proprietà P 2. Se non lo troviamo,esito positivo, altrimenti negativo. I Lo schema generale per risolvere questo problema. int trovato = FALSE; int x=a; while (x<b &&!trovato) if (!P(x)) trovato = TRUE; x=x+1; if (trovato) /* esito negativo */ /* esito positivo */ C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 40
Alternativamente Possiamo ipotizzare che la proprietà sia valida per tutti gli elelmenti, e verificare se esiste un elemento per cui non lo sia. int tutti = TRUE; int x=a; while (x<b && tutti) if (!P(x)) tutti = FALSE; x=x+1; if (tutti) /* esito positivo */ /* esito negativo */ C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 41
Esempio: Sono dispari tutti gli elementi di un array? Cerchiamo il primo elemento pari! int trovato=false; int i=0; while (i<dim &&!trovato) if (vet[i] % 2 == 0) trovato=true; i=i+1; if (trovato) printf("il controllo ha dato esito negativo" ); printf("il controllo ha dato esito positivo" ); C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 42
Esercizio: Ricerche incerte più complesse I Si vogliono determinare, se esistono il minimo elemento di un intervallo [a,b) eilminimoelementodiunintervallo[c,d) per i quali vale una certa proprietà P, ovvero se: I Analogamente determinare se: I Analogamente determinare se: I Analogamente determinare se: 9i 2 [a, b), 9j 2 [c, d) :P(i, j) 9i 2 [a, b), 8j 2 [c, d) :P(i, j) 8i 2 [a, b), 9j 2 [c, d) :P(i, j) 8i 2 [a, b), 8j 2 [c, d) :P(i, j) L uscita da ogni ciclo va controllata con apposite guardie booleane, possibilmente distinte tra un ciclo e l altro. C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 43
Soluzione quesito 1 I Si vogliono determinare, se esistono il minimo elemento di un intervallo [a,b) eilminimoelementodiunintervallo[c,d) per i quali vale una certa proprietà P, ovvero se: 9i 2 [a, b), 9j 2 [c, d) :P(i, j) int esiste = FALSE; int i = a; while (i<b &&!esiste) {int j = c; while (j<d &&!esiste) if (P(i,j)) esiste = TRUE; j=j+1; if (!esiste) i = i+1; } C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 44
Soluzione quesito 2 I Si vuole determinare se: 9i 2 [a, b), 8j 2 [c, d) :P(i, j) int esiste = FALSE; int i = a; while (i<b &&!esiste ) {int tutti = TRUE; int j = c; while (j<d && tutti) if (!P(i,j)) tutti= FALSE; j =j+1; } if (tutti) esiste = TRUE; i = i+1;} C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 45
Soluzione quesito 3 I Si vuole determinare se: 8i 2 [a, b), 9j 2 [c, d) :P(i, j) int tutti = TRUE; int i = a; while (i<b && tutti) {int esiste = FALSE; int j = c; while (j<d &&!esiste) if (P(i,j)) esiste= TRUE; j =j+1; } if (!esiste) tutti = FALSE; i = i+1;} C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 46
Soluzione quesito 4 I Si vuole determinare se: int tutti = TRUE; int i = a; while (i<b && tutti) {int j = c; while (j<d && tutti) if (!P(i,j)) tutti = FALSE; j=j+1; if (tutti) i = i+1; } 8i 2 [a, b), 8j 2 [c, d) :P(i, j) C. Bodei Dip.to Informatica FONDAMENTI DI PROGRAMMAZIONE a.a. 17/18 pag. 47