Algoritimi Moreno Marzolla Dipartimento di Informatica—Scienza e Ingegneria (DISI) Università di Bologna http://www.moreno.marzolla.name/ Algoritmi 2 Algoritmi 3 Algoritmi ● ● Un algoritmo è un procedimento per risolvere un problema mediante una sequenza finita di passi elementari – Descritto in modo preciso allo scopo di automatizzarne l'esecuzione Il termine deriva dal nome del matematico persiano Muhḥammad ibn Mūsā alKhwārizmī ()محمد بن موسى الخوارزمی – Autore di un primo fondamentale trattato di algebra (الكتاب المختصر في حساب الجبر والمقابلةal-Kitāb almukhtasḥar fī hḥisāb al-jabr walmuqābala) – Un cratere lunare porta il suo nome Algoritmi Muhḥammad ibn Mūsā al-Khwārizmī (c. 780 – c. 850) (francobollo sovietico commemorativo; Fonte: Wikipedia) 4 Proprietà di un algoritmo ● Atomicità – ● Non ambiguità – ● L'algoritmo deve essere composto da un numero finito di passi e richiedere una quantità finita di risorse (di qualunque tipo) per la sua esecuzione; Terminazione – ● I passi devono essere interpretabili in modo diretto e univoco dall'esecutore, sia esso umano o artificiale; Finitezza – ● I passi costituenti devono essere elementari, cioè non ulteriormente scomponibili; L'esecuzione deve avere termine dopo un tempo finito; Effettività – L'esecuzione deve portare ad un risultato univoco. Algoritmi 5 E' un algoritmo? ● ● ● ● ● Atomicità Non ambiguità Finitezza Terminazione Effettività "Tutte le qualità di funghi possono fare al caso; ma io ritengo che i porcini sieno da preferirsi, esclusi però i grossissimi. Nettateli bene dalla terra e lavateli, poi tritateli minuti alla grossezza di un cece o anche meno. Metteteli al fuoco con burro, sale e pepe e quando avranno soffritto alquanto, tirateli a cottura con sugo di carne. Ritirati dal fuoco, legateli con balsamella, uova e parmigiano e assodate il composto a bagno-maria. Grammi 600 di funghi in natura con cinque uova faranno uno sformato bastante per dieci persone. Servitelo caldo e per tramesso." [Pellegrino Artusi (1910), La scienza in cucina e l'arte di mangiar bene, 452 Sformato di Funghi] Algoritmi 6 Cosa si intende per "istruzione elementare"? ● ● Dipende dall' "esecutore" che consideriamo Nell'esempio "culinario", le istruzioni devono essere tali da poter essere eseguite in modo non ambiguo da chiunque voglia cimentarsi con la cucina – – – – – "Separare il tuorlo dell'uovo dall'albume" "Versare due cucchiaini di zucchero nel composto" "Portare l'acqua ad ebollizione" "Frullare il composto per 5 min" ... Algoritmi 7 Cosa si intende per "istruzione elementare"? ● Noi considereremo come "istruzioni elementari" cose del tipo: – Assegnare un valore ad una variabile ● – Calcolare il valore di una espressione aritmetica ● – – Es: b ← (3+a)*5 - 1 Confrontare il valore di due espressioni ● – Es: a ← 5 Es: a < (b+3) Chiedere all'utente l'inserimento di un valore, oppure visualizzare un valore ... Algoritmi 8 Come si descrive algoritmo? ● ● ● Linguaggio naturale Pseudocodice Notazioni grafiche (diagrammi di flusso o flowchart) Algoritmi 9 Esempio: Massimo Comun Divisore Descrizione in linguaggio naturale 1.Siano n e m due valori interi positivi 2.Se n = m, termina indicando n come risultato 3.Se n > m: – – assegna a n il valore (n - m); torna al punto 2 4.Se n < m: – – assegna a m il valore (m - n); torna al punto 2 Algoritmi 10 Vantaggi e svantaggi del linguaggio naturale ● Vantaggi – ● Notazione comprensibile anche ai non esperti Svantaggi – – Algoritmi Il linguaggio naturale può risultare verboso, e quindi produrre una descrizione prolissa Persone diverse hanno stili di scrittura diversi, e questo può in certi casi generare ambiguità 11 Esempio: Massimo Comun Divisore Descrizione mediante pseudocodice Precondizione: quali proprietà devono valere perché l'algoritmo fornisca il risultato desiderato Postcondizione: quali proprietà valgono al termine dell'esecuzione, nell'ipotesi in cui le precondizioni siano soddisfatte Pre: n, m interi > 0 Post: Stampa il MCD(n,m) while (n ≠ m) do if (n > m) then n ← n – m; else m ← m – n; end if end while Stampa n; Algoritmi 12 Vantaggi e svantaggi dello pseudocodice ● Vantaggi – – – ● Consente descrizioni più precise e meno verbose rispetto al linguaggio naturale Può essere compreso anche da utenti non esperti purché abbiano una minima confidenza con la notazione Facilita la traduzione dell'algoritmo in un "vero" linguaggio di programmazione Algoritmi Svantaggi – Notazione non univoca: non esiste un unico “tipo” di pseudocodice 13 Esempio: Massimo Comun Divisore Descrizione mediante flowchart L'esecuzione inizia da questo nodo Nodo condizionale: deve contenere una espressione che da come risultato vero/falso Inizio F n≠m V F V n>m m←m-n n←n-m Stampa n L'esecuzione termina in questo nodo Algoritmi Fine Nodo di input/output: indica che si chiede l'immissione o la stampa di valori 14 Vantaggi e svantaggi dei diagrammi di flusso ● Vantaggi – – – ● Notazione di facile comprensione anche per non esperti Consente di individuare “a colpo d'occhio” strutture particolari come cicli e condizioni Esistono software per “disegnare” flowchart, e convertirli in codice eseguibile Algoritmi Svantaggi – Possono risultare confusi per algoritmi di dimensioni medio-grandi ● – I flowchart richiedono uno spazio maggiore rispetto alle descrizioni testuali Se abusati, possono produrre descrizioni incomprensibili ● Vedi seguito 15 Flowchart ● In linea di principio, un diagramma di flusso può avere una struttura arbitraria... – ● cioè è possibile connettere i blocchi in qualsiasi modo ...però questa libertà può portare ad algoritmi difficili (impossibili?) da comprendere Algoritmi 16 Programmazione strutturata ● Paradigma di programmazione in cui qualsiasi algoritmo viene espresso combinando tra loro alcune strutture di controllo fondamentali – – – ● Sequenza Condizione Iterazione La programmazione strutturata consente di descrivere algoritmi in modo più comprensibile e meno soggetto a errori – Può a volte risultare utile deviare dalle rigide regole della programmazione strutturata Algoritmi 17 Costrutti fondamentali Sequenza S1 S2 S1 S2 Condizione: if-then C if C then S end if F V S Condizione: if-then-else if C then Strue else Sfalse end if Algoritmi F Sfalse C V Strue 18 Costrutti fondamentali Iterazione: for Iterazione: while-do C while C do S end while F for v ← a to b do S end for V S v←a v≤b V Iterazione: do-while S S do S while C F V C v←v+1 F Algoritmi 19 Composizione ● E' possibile rimpiazzare i blocchi tratteggiati con altri costrutti (proprietà di composizione) Inizio n≠m F F m←m-n V n>m V n←n-m Fine Stampa n Algoritmi 20 Esempio: Elevamento a potenza ● Scrivere un algoritmo che, dati in input un numero reale x ≠ 0 e un intero n ≥ 0, calcola il valore xn n x =⏟ x×x …×x n volte – Per definizione si ha che x0 = 1 Algoritmi 21 Elevamento a potenza Inizio Leggi x, n Pre: x ≠ 0, n intero ≥ 0 Post: Stampa p = xn p←1 p ← 1 while (n > 0) do p ← p * x n ← n – 1 end while Stampa p n>0 F V p←p*x n←n-1 Stampa p Algoritmi Fine 22 Esempio: Massimo e Minimo ● Dato un array (vettore) di valori reali v0, v1, … vn-1, scrivere un algoritmo per determinare il valore massimo e minimo presente nell'array – – ● Se tutti i valori sono uguali, massimo e minimo coincidono Se l'array ha un solo elemento (n = 1), massimo e minimo coincidono con l'unico valore presente Un array di n elementi può essere intuitivamente immaginato come un insieme di n "scatole" (celle), ciascuna etichettata con un intero da 0 a n – 1 e contenente un valore Celle dell'array 21 6 7 -2 15 0 1 2 3 4 Algoritmi 41 33 41 5 6 7 23 Indici delle celle Inizio Possibile soluzione Min ← v0 Max ← v0 i←1 Pre: v0, v1, … vn-1 array non vuoto di valori reali (n ≥ 1) Post: Min, Max sono i valori minimo e massimo presenti nell'array Min ← v0 Max ← v0 for i ← 1 to n-1 do if (vi < Min) then Min ← vi else if (vi > Max) then Max ← vi end if end for Stampa Min, Max; i<n F V F F vi > Max vi < Min V V Min ← vi Max ← vi i←i+1 Stampa Min, Max Algoritmi Fine 24 Esempio: Ricerca Binaria ● ● ● Dati: – Un array di valori reali distinti v0, v1, … vn-1 ordinati in senso crescente (v0 < v1 < … < vn-1 ) – Un valore reale k (arbitrario) Determinare la posizione di k nell'array (se presente) – Cioè determinare l'indice i, se esiste, tale che vi = k – Se k non compare nell'array, restituire -1 Es: v0 v1 v2 v3 v4 v5 v6 v7 -3 -1 2 5 6 13 15 21 Algoritmi k = 13 Il risultato deve essere 5 25 Esempio ● Ricerca di k = 7 2 3 7 12 Algoritmi 18 21 27 26 Esempio ● Ricerca di k = 7 2 3 7 12 Algoritmi 18 21 27 27 Esempio ● Ricerca di k = 7 2 3 7 12 Algoritmi 18 21 27 28 Esempio ● Ricerca di k = 7 2 3 7 12 Algoritmi 18 21 27 29 Esempio ● Ricerca di k = 7 2 3 7 12 Algoritmi 18 21 27 30 Esempio ● Ricerca di k = 7 2 3 7 12 18 21 27 Trovato! Algoritmi 31 Esempio ● Ricerca di k = 20 2 3 7 12 Algoritmi 18 21 27 32 Esempio ● Ricerca di k = 20 2 3 7 12 Algoritmi 18 21 27 33 Esempio ● Ricerca di k = 20 2 3 7 12 Algoritmi 18 21 27 34 Esempio ● Ricerca di k = 20 2 3 7 12 Algoritmi 18 21 27 35 Esempio ● Ricerca di k = 20 2 3 7 12 Algoritmi 18 21 27 36 Esempio ● Ricerca di k = 20 2 3 7 12 Algoritmi 18 21 27 37 Esempio ● Ricerca di k = 20 2 3 7 12 18 21 27 Non trovato! Algoritmi 38 Domande ● Dato un array ordinato di n elementi: – – Quanti elementi bisogna esaminare nel caso migliore? Quanti elementi bisogna esaminare nel caso peggiore? Algoritmi 39 Funzionamento dell'algoritmo ● ● Usiamo due valori interi i (inizio) e f (fine) per rappresentare la posizione (indice) del primo e dell'ultimo elemento della porzione di array in cui potrebbe trovarsi il valore cercato Indichiamo con m (mezzo) l'indice dell'elemento che occupa la posizione centrale nel sottovettore v i … vf i=0 m=3 f=6 v0 v1 v2 v3 v4 v5 v6 2 3 7 12 18 21 27 Cerchiamo k = 3 Algoritmi 40 Funzionamento dell'algoritmo ● ● Usiamo due valori interi i (inizio) e f (fine) per rappresentare la posizione (indice) del primo e dell'ultimo elemento della porzione di array in cui potrebbe trovarsi il valore cercato Indichiamo con m (mezzo) l'indice dell'elemento che occupa la posizione centrale nel sottovettore v i … vf i=0 m=3 f=6 v0 v1 v2 v3 v4 v5 v6 2 3 7 12 18 21 27 Cerchiamo k = 3 Algoritmi 41 Funzionamento dell'algoritmo ● ● Usiamo due valori interi i (inizio) e f (fine) per rappresentare la posizione (indice) del primo e dell'ultimo elemento della porzione di array in cui potrebbe trovarsi il valore cercato Indichiamo con m (mezzo) l'indice dell'elemento che occupa la posizione centrale nel sottovettore v i … vf i=0 m=1 f=2 v0 v1 v2 v3 v4 v5 v6 2 3 7 12 18 21 27 Trovato in posizione m = 1 Algoritmi 42 Pseudocodice primo tentativo Pre: v0, v1, … vn-1 array non vuoto ordinato, valore k Post: stampa la posizione del valore k nell'array, se presente, altrimenti stampa "non trovato" i ← 0 f ← n - 1 while "sottovettore non vuoto" do m ← "posizione centrale nel sottovettore vi … vf" if (vm = k) then stampa "Trovato in posizione:" m; stop else "aggiorna estremi i ed f" endif endwhile stampa "Non trovato" Algoritmi 43 Primo raffinamento ● Come facciamo a "calcolare la posizione centrale nel sottovettore vi … vf" ? (f – i + 1) elementi i m f ... ... Circa (f – i)/2 elementi Circa (f – i)/2 elementi m = i + (f – i) / 2 = (i + f) / 2 Algoritmi 44 Attenzione... ● Controlliamo se funziona anche in casi particolari i=1 f=2 m = (1 + 2) / 2 = 1 i=4 f=4 m = (4 + 4) / 2 = 4 Algoritmi 45 Pseudocodice raffinamento Pre: v0, v1, … vn-1 array non vuoto ordinato; valore k Post: stampa la posizione del valore k nell'array, se presente, altrimenti stampa "non trovato" i ← 0 f ← n - 1 while "sottovettore non vuota" do m ← (i + f) / 2; if (vm = k) then stampa "Trovato in posizione:" m; stop else "aggiorna estremi i ed f" endif endwhile stampa "Non trovato" Algoritmi 46 Secondo raffinamento ● Se il valore centrale non è quello cercato, come aggiornare il valore di i ed f ? – Caso 1: il valore centrale è troppo grande (es., cerchiamo 3, valore centrale è 12) i 2 m 3 i 2 7 f 12 18 21 27 12 18 21 27 f 3 7 Algoritmi 47 Secondo raffinamento ● Se il valore centrale non è quello cercato, come aggiornare il valore di i ed f ? – Caso 2: il valore centrale è troppo piccolo (es., cerchiamo 21, valore centrale è 12) i 2 m 3 7 12 f 18 21 i 2 3 7 12 Algoritmi 18 27 f 21 27 48 Pseudocodice ulteriore raffinamento Pre: v0, v1, … vn-1 array non vuoto ordinato, valore k Post: stampa la posizione del valore k nell'array, se presente, altrimenti stampa "non trovato" i ← 0 f ← n - 1 while "sottovettore non vuoto" do m ← (i + f) / 2; if (vm = k) then stampa "Trovato in posizione:" m; stop else if (vm > k) then f ← m – 1; else i ← m + 1; endif endif endwhile Algoritmi stampa "Non trovato" 49 Raffinamento finale ● ● L'algoritmo termina quando non ci sono più elementi da esaminare Es: cerchiamo k = 13 i=0 m=1 f=2 i ← 0 f ← n - 1 while "sottovettore non vuoto" do m ← (i + f) / 2; if (vm = k) then stampa "Trovato in posizione:" m; stop else if (vm > k) then f ← m – 1; else i ← m + 1; endif endif endwhile stampa "Non trovato" Algoritmi 2 2 2 12 15 i=2 m=2 12 15 f=1 i=2 12 15 f=2 50 Pseudocodice versione finale Pre: v0, v1, … vn-1 array non vuoto ordinato, valore k Post: stampa la posizione del valore k nell'array, se presente, altrimenti stampa "non trovato" i ← 0 f ← n - 1 while (f ≥ i) do m ← (i + f) / 2; if (vm = k) then stampa "Trovato in posizione:" m; stop else if (vm > k) then f ← m – 1; else i ← m + 1; endif endif endwhile Algoritmi stampa "Non trovato" 51 Esercizio per casa Ricerca sequenziale ● Dati: – – ● Un array di valori reali v0, v1, … vn-1 non necessariamente distintie non ordinati Un valore reale k (arbitrario) Determinare la posizione di k nell'array (se presente) – Cioè determinare un indice i, se esiste, tale che vi = k – Se esistono più elementi dell'array con valore k è possibile restituire l'indice di una qualunque occorrenza Se k non compare nell'array, restituire -1 – Algoritmi 52 Esercizio per casa Primo e secondo minimo ● ● Dato un array di valori reali distinti v0, v1, … vn-1 con almeno due elementi (n ≥ 2), scrivere un algoritmo per determinare i due valori minimi Es: – – 1, 9, -3, 7, 5, 12, 4 → ritorna -3, 1 1, 2, 3, 4, 5 → ritorna 1, 2 Algoritmi 53 Primo e secondo minimo ● Idea: esaminiamo uno per uno gli elementi dell'array Supponiamo di aver determinato i valori Min1, Min2 del primo e secondo minimo del sottovettore v1, v2, … vi – 1 ● Esaminiamo il valore vi ● Tre casi possibili ● vi Min1 – vi < Min1 – Min1 < vi < Min2 Min1 – vi > Min2 Min1 Min2 vi Min2 Min2 vi (Per ipotesi tutti i valori sono distinti, quindi non si potrà mai verificare che vi = Min1 oppure vi = Min2) Algoritmi 54 Primo e secondo minimo In ciascuno dei tre casi, come dobbiamo modificare i valori Min1 e Min2 affinché essi siano ancora il primo e il secondo minimo del sottovettore v0, v1, … vi? ● vi Min1 Min1 Min1 ● Min2 vi Min1 Min2 Min2 Min2 Min1 Min2 Min1 vi Min2 Come definiamo Min1 e Min2 all'inizio? Algoritmi 55 Esercizio per casa Deposito ● Il primo gennaio dell'anno zero, Augusto deposita l'equivalente di 1 Euro in banca, negoziando un tasso composito del 5% annuo – Il primo gennaio dell'anno 1 si trova nel conto 1(1+0.05) = 1.05 Euro – Il primo gennaio dell'anno 2 si trova nel conto 1.05(1+0.05) = 1.1025 Euro – Il primo gennaio dell'anno 3 si trova nel conto 1.1025(1+0.05) = 1,157625 Euro … e così via – ● ● ● Il primo gennaio dell'anno zero, Claudia deposita l'equivalente di 100 Euro in banca, negoziando un tasso composito del 4% annuo Entrambi i depositi vengono tramandati di generazione in generazione, alle stesse condizioni In quale anno l'importo presente nel conto (degli eredi) di Augusto diventa strettamente maggiore di quello presente nel conto (degli eredi) di Claudia? Algoritmi 57