Scarica Vincitrice concorso straordinario e idonea concorso ordinario 2022 e più Appunti in PDF di Informatica solo su Docsity! Modulo 1, Parte 2 Codifica digitale delle informazioni 3 Codici digitali non pesati 4 Il Barcode 4 Il QR Code 5 Codici digitali pesati 5 Codici digitali binari pesati 9 Codice ASCII 9 Codice UNICODE 10 UTF-8 10 UTF-16 10 UTF-32 10 Processi algoritmici e processi euristici 11 Concetto di algoritmo 11 I Flow Chart 12 Valori e grandezze 13 Variabili 14 Le strutture di controllo 14 Selezione semplice 15 Selezione IF-ELSE 15 Ciclo While-do 16 Ciclo do-while 17 Ciclo while-do VS do-while 18 Ciclo for 18 Concetto di equivalenza 19 Processi Euristici 20 Problema del commesso viaggiatore 21 Complessità computazionale TSP 24 Ciclo Hamiltoniano 24 Problema dello zainetto 25 Problemi algoritmici VS Problemi euristici 26 Algoritmi Greedy 26 Complessità computazionale 27 Limite asintotico Superiore 28 Limite asintotico Inferiore 29 Limite asintotico Stretto 30 La notazione asintotica (θ) è un limite asintotico stretto. 31 Calcolo del limite asintotico 31 Regole calcolo del CC 32 Algoritmi notevoli 43 Ricerca sequenziale 43 Ricerca Binaria o logaritmica 44 Ricerca Binaria ricorsiva 46 Ricerca Sequenziale VS Ricerca Binaria 46 Stupid Sort 46 Selection Sort 47 Bubble Sort 48 Insertion Sort 49 Shell Sort 50 Quick Sort 51 Merge Sort 52 QuickSort VS Merge Sort 54 Confronti CC algoritmi di ordinamento 55 Il QR Code ● Il QR Code è stato sviluppato nel 1994 in Giappone e utilizza per la codifica delle informazioni un sistema a barre bidimensionali a matrice. ● Il codice QR Code può memorizzare fino ad un massimo di 4296 caratteri alfanumerici e 7089 numerici. ● Il processo di codifica di una informazione in QR Code viene detto : QURIFICAR ● Il processo di decodifica di una informazione in QR viene detto : DEQURIFAR Codici digitali pesati I codici digitali pesati prevedono l'esistenza di : 1. Un alfabeto sorgente: A=(A1,A2,....,An), avente cardinalità2 N. 2. Un alfabeto codice: B=(B1,B2,....,Bm) , avente cardinalità M; I codici digitali pesati possono essere : 1.Codice digitale a lunghezza variabile: ● Le parole dell'alfabeto in codice, usate per codificare i simboli o le parole dell'alfabeto sorgente hanno lunghezza variabile. 2.Codice digitale a lunghezza fissa : ● Le parole dell'alfabeto in codice, usate per codificare i simboli o le parole dell'alfabeto sorgente hanno lunghezza fissa; ● Lunghezza delle parole di codice nella codifica a lunghezza fissa : ● Il numero di parole di codice di lunghezza L che è possibile ottenere è M^(L) : ○ Se M^(L) > N allora il codice a lunghezza fissa si dice ridondante3; ○ Se M^(L) = N allora il codice a lunghezza fissa si dice non ridondante4; Esempio : 4 Un codice si dice non ridondante se : Il numero di combinazioni delle parole o di simboli dell' alfabeto in codice è uguale della cardinalità dell'alfabeto sorgente; 3 Un codice si dice ridondante se : Il numero di combinazioni delle parole o di simboli dell'alfabeto in codice è maggiore della cardinalità dell'alfabeto sorgente. 2 La cardinalità di un insieme è definita come il numero degli elementi di un insieme .
> Dato l'alfabeto sorgente :
A = (uno, due, tre, quattro, cinque, sei, sette, otto,
nove)
Codificare le stringhe dell'insieme A con il seguente
empio codice non ridondante
alfabeto in codice
a lunghezza fissa e lunghezza
euro
B=(G,F,E)
Usando una codifica a lunghezza fissa e variabile
lice non rit mi inghezza fissa :
» Procedimento :
1. Determinare la lunghezza delle parole codice
2. Determinare il numero di possibili combinazioni
3. Effettuare la codifica
» Risoluzione :
1. Determinare la lunghezza delle parole codice :
O L'alfabeto sorgente A ha cardinalità 9
o L'alfabeto in codice B ha cardinalità 3
Quindi :
L li codice è:
L = INTmnax (109, 9)
Ilnumi i combinazioni ibili è: |3
Codice UNICODE Il codice ASCII a 8 bit non è adatto per le lingue orientali che usano migliaia di ideogrammi. È necessaria una codifica che usi almeno 16 bit (65.536 caratteri).Nel 1991 è stato istituito il consorzio Unicode per definire uno standard a 16 bit internazionale, noto come codice Unicode: ● Il set di caratteri Unicode comprende le lettere di tutti gli alfabeti,molti simboli speciali e ideogrammi; ● L'insieme dei caratteri del codice Unicode prende il nome di UCS (Universal Character Set) ● Il codice Unicode usa 3 sotto codifiche chiamate UTF (UCS Transformation Format) al fine di ottimizzare la memorizzazione, la comunicazione e l'interpretazione da parte dei dispositivi : 1. UTF-8; 2. UTF-16; 3. UTF-32. UTF-8 La codifica UTF-8 codifica a lunghezza variabile usata nelle comunicazioni ad esempio la produzione di pagine web UTF-16 La codifica UTF-16 codifica a lunghezza variabile usata nelle elaborazioni applicative come ad esempio il java UTF-32 La codifica UTF-32 codifica a lunghezza fissa poco usata perché comporta un notevole uso di memoria Processi algoritmici e processi euristici Concetto di algoritmo Un algoritmo è un procedimento che permette la risoluzione di specifici problemi mediante l’applicazione di una sequenza finita di precise istruzioni che, a loro volta, devono essere interpretate ed eseguite fino alla loro conclusione seguendo un ben preciso ordine. Un algoritmo DEVE ESSERE GENERALE : la soluzione è uguale per tutti i problemi della medesima classe. Ogni algoritmo gode delle seguenti proprietà fondamentali : ● Atomicità : i passi dell’algoritmo devono essere elementari, cioè non possono essere ulteriormente divisibili; ● Non ambiguità : i passi dell’algoritmo non possono essere interpretati in altri modi anche se l'esecutore è differente; ● Finitezza : l’algoritmo deve essere svolto in un numero finito di passi e, allo stesso tempo, deve richiedere in ingresso soltanto una determinata quantità di dati; ● Terminazione : l'esecuzione dell’algoritmo deve terminare entro un certo periodo di tempo; ● Determinismo : l’esecuzione dell’algoritmo deve portare ad un risultato univoco, cioè partendo dagli stessi dati in input, si ottengono i medesimi risultati in output. I Flow Chart I diagrammi di flusso utilizzano cinque distinti blocchi: 1. inizio; 2. ingresso/uscita; 3. elaborazione; 4. controllo; 5. fine. Gli elementi caratterizzanti di un algoritmo sono : 1. Valori e grandezze; 2. Variabili; 3. Espressioni; ● repeat-until: ripeti le istruzioni fino a quando la condizione non risulta vera Selezione semplice La selezione semplice : ● permette di eseguire un'istruzione, o blocco di istruzioni, al verificarsi di una condizione; ● ciascun blocco di controllo ha una sola freccia entrante e due frecce uscenti Selezione IF-ELSE La selezione IF-ELSE: ● permette di scegliere tra due possibili azioni mutuamente esclusive; ● ciascun blocco di controllo ha una sola freccia entrante e due frecce uscenti. Ciclo While-do While-do : blocco iterativo con controllo in testa; ● Permette di ripetere un blocco di istruzioni finché la condizione logica rimane vera; ● Il blocco potrebbe non venire mai eseguito se la condizione è subito falsa Esempio : Ciclo do-while Do-While: blocco iterativo con controllo in coda; ● Permette di eseguire almeno una volta il blocco contenuto nel ciclo; ● Si ripete il blocco finché la condizione logica viene verificata.Esempio : Esempio : Il passaggio da uno schema a blocchi non strutturato ad uno strutturato può avvenire attraverso la duplicazione di blocchi, ottenendo schemi fortemente equivalenti Processi Euristici In informatica si definisce euristico il lavoro di un algoritmo che non opera meccanicamente, ma utilizza invece una tecnica virtualmente creativa, cioè non si limita ad analizzare i dati secondo confronto di dati noti, ma prova a simularne il comportamento (Wikipedia). Un algoritmo euristico è un algoritmo semplificato rispetto agli algoritmi, non indica con precisione ogni azione che il soggetto impegnato nella soluzione del problema deve o dovrebbe intraprendere, e non garantisce, inoltre, il raggiungimento della soluzione del problema di partenza Un algoritmo euristico è impiegato quando : ● la risoluzione ottimale del problema può essere impossibile; ● la risoluzione ottimale del problema può essere troppo costosa in termini di tempo o di capacità di elaborazione. Esempi di algoritmi Euristici : 1. Algoritmo risolutivo del Problema del commesso viaggiatore; 2. Algoritmo risolutivo del Problema dello zaino; 3. Algoritmo di Kernighan-Lin Problema del commesso viaggiatore Il problema del commesso viaggiatore è noto in inglese come : Traveling Salesman’s Problem (TSP) : ● Un commesso viaggiatore deve visitare un certo numero di città. ● Conosce la distanza da una città all’altra; ● Vuole determinare il percorso più breve che gli permetta di partire da casa sua e di farvi ritorno dopo aver visitato ogni città una sola volta; Risoluzione : Il problema del TSP applicato ai grafi può essere espresso nel seguente modo : Dato un grafo G con archi pesati calcolare un Ciclo Hamiltoniano di Costo Minimo Problema dello zainetto Abbiamo uno zaino e vogliamo riempirlo con un pò di oggetti: ● La nostra forza è limitata, e quindi riusciamo a trasportare al massimo un certo peso : ● Ogni oggetto ha un certo valore; Vogliamo trasportare oggetti in modo da da massimizzare il valore del trasporto Una delle possibili soluzione consiste nell’usare un metodo di forza bruta : esaminiamo tutte i possibili sottoinsiemi di n oggetti e scegliere il sottoinsieme con un peso ammissibile che massimizza il valore La soluzione è poco efficiente perchè : con n oggetti tutti i possibili sottoinsiemi da esaminare sono 2^(n); Problemi algoritmici VS Problemi euristici Algoritmo : ● un algoritmo è una procedura formale, deterministica, fatta di passi elementari, in sequenza finita; ● un algoritmo riceve i dati e produce la soluzione; ● un algoritmo è una dimostrazione di correttezza; Euristica : ● un’euristica è una regola informale, creativa, aperta; ● un’euristica riceve i dati e produce “qualcosa”; ● un’euristica è un insieme di considerazioni di buon senso. Algoritmi Greedy La tecnica di progettazione di algoritmi di tipo Greedy, si basa sulla semplice strategia dell’ingordo, ovvero, quella di compiere, ad ogni passo, la scelta migliore nell’ immediato piuttosto che adottare una strategia a lungo termine. Non sempre è garantita la correttezza, ma sono spesso molto semplici ed efficienti. Complessità computazionale La complessità computazionale riguarda essenzialmente due aspetti: 1. Lo spazio occupato dall’algoritmo; 2. Il tempo di esecuzione Per misurare l'efficienza di un algoritmo in maniera univoca, bisogna definire una metrica indipendente dalle tecnologie utilizzate, altrimenti uno stesso algoritmo potrebbe avere efficienza diversa a seconda della tecnologia sulla quale è eseguito. Per questo motivo si usa fare riferimento ad un modello di calcolo generico: la macchina di Turing. Questo significa che : Qualunque modello di calcolo scelto, ai fini della classificazione dei problemi, si comporta come la macchina di Turing. La tesi di Church-Turing afferma, infatti, che la classe delle funzioni calcolabili coincide con quella delle funzioni calcolabili da una macchina di Turing. La notazione asintotica Ω è il limite asintotico inferiore. Limite asintotico Stretto Cioè g(n) cresce altrettanto rapidamente rispetto a f(n). Se un algoritmo è 𝞡(f(n)) significa non ci sono variazioni significative di prestazioni tra il caso migliore e il caso peggiore. La notazione asintotica (θ) è un limite asintotico stretto. Calcolo del limite asintotico Per determinare i limiti asintotici di due funzioni f(n) e g(n) si utilizza il metodo del limite del rapporto f(n)/g(n): Regole calcolo del CC Per valutare le prestazioni di un algoritmo si considerano: 1. Il caso ottimo: caso in cui i dati sono i migliori dati possibili per l'algoritmo, cioè quelli che richiedono meno elaborazioni per essere trattati 2. Il caso peggiore: caso in cui i dati che richiedono il massimo numero di passi per l'algoritmo. 3. Il caso medio: è il caso che fornisce un reale indicatore della complessità dell'algoritmo. A volte, per risolvere il problema del caso medio si preferisce eseguire molte simulazioni dell'algoritmo e poi, dai tempi ottenuti con le simulazioni, estrarre una formula che si approssimi adeguatamente all'andamento medio. Regole di base : 1. Costo computazionale CC = O(1) : ● funzione IF; ● funzioni aritmetiche; ● funzione logiche; ● funzione di confronto; ● funzione di assegnamento. 2. Costo computazionale CC = log (n) : ● Per identificare quest’ordine di funzione bisogna notare se il problema ha un numero di elementi che viene dimezzato ogni volta (algoritmo di ricerca binaria: ad ogni iterazione il numero di elementi dell’array da esaminare viene dimezzato) 3. Costo computazionale CC = O(f(n)) : ● costo computazionale di una chiamata a funzione. 1. Assegnamento esterno: 1 2. Numero di test: 2*n+1 3. Assegnamenti interni: 2*(2*n) ● Numero totale di passi base: 6*n+2 5. Calcolo della complessità in numero di passi base La complessità in passi base di questo blocco è: 5. Calcolo della complessità dei cicli annidati 6. Complessità di programmi in base ai valori di ingresso Supponiamo di avere il seguente vettore A contenente 14 elementi: A = {3, -2, 0, 7, 5, 4, 0, 6, -3, -1, 9, 12, 20, 5} Usiamo, per risolvere il problema il seguente algoritmo di ricerca lineare : i = 0; while(i<n && A[i] != x) i = i+1; dove ● n è la dimensione dell’array; ● x il numero da cercare. 1.Caso migliore : X = 3 è il primo elemento dell’array : Il costo computazionale è pari : ● 1 assegnazione; ● 1 test; quindi : CC = 2 2. Caso peggiore : X = 5 è l’ultimo elemento dell’array : Il costo computazionale è pari : ● 1 assegnazione; ● n test; ● n - 1 cicli quindi : CC = 2n 3. Caso medio: Consideriamo un’ipotesi di distribuzione uniforme, ovvero che i valori siano disposti casualmente nel vettore. Poiché i valori sono distribuiti uniformemente, la probabilità di trovare l’elemento cercato in posizione i nel vettore (di dimensione n) è: ● P = 1/n Il numero di operazioni di test da eseguire per trovare l’elemento cercato nella posizione i è : ● C(i) = i quindi: 4. Caso peggiore : X = 22 l’ elemento non esiste nell’array : Il costo computazionale è pari : ● 1 assegnazione; ● n test; ● n + 1 cicli quindi : CC = 2n + 2 7.Complessità di programmi strutturati 10. Complessità dei blocchi annidati 1. Sia g1 (n) la complessità del blocco esterno; 2. Sia g2 (n) la complessità del blocco interno. La complessità di un blocco costituito da più blocchi annidati è data dal prodotto delle complessità dei blocchi componenti: 11. Prodotto tra matrici
Consideriamo due algoritmi che calcolano il valore minimo e del valore massimo degli elementi di un array
I Algoritmo :
Assegnazione = O(1)
* Iî=01);
= Assegnazione = (1);
* If=0(1);
=» Assegnazione = O(1);
*_Ndi volte in cui viene eseguito = n;
Quindi : CC = O(n)* 4* O(1) = O(m)
Algoritmo Il :
Assegnazione = 0(1)
* Ndi volte in cui viene
f eseguito il ciclo = n;
Quindi
CC=O(n)* 2* 0(1) = O(m)
[MESE 3 344) dl
(array[i] < min)
È ESTESI
*Ndi volte in cui viene
eseguito il ciclo
= (1):
Assegnazione = 0(1);
Quindi :
CC=OMm* 2* 0(1)= O(m)
o
O(n) +0(m) = Om),
1f= 001);
Assegnazione = 0(1)
NB : Questo algoritmo ha 2 cicli for sequenziali :
Regola : il CC di due cicli for sequenziali è uguale alla somma dei CC dei singoli cicli
a CC =0(m) + O(n) = 0(m)
Se i cicli for sono annidati come si calcola il CC ?
Regola : il CC di due cicli for annidati è uguale al prodotto dei CC dei singoli cicli
+ Ndi volte în cui viene
eseguito il ciclo = n;
Quindi :
CC=0(m)* 0(1) = 0(m)
* Ndi volte in cui viene
eseguito il ciclo = n;
Quindi :
CC=0Mm* 2* 0(1)= O(m)
CC = O(n) * O(n) = O(n42)
Il valore ricercato viene confrontato con il valore dell'elemento centrale dell'insieme : 1. Se corrisponde: la ricerca termina indicando che l'elemento è stato trovato; 2. Se è inferiore: la ricerca viene ripetuta sugli elementi precedenti (ovvero sulla prima metà del dizionario), scartando quelli successivi; 3. Se è superiore: la ricerca viene ripetuta sugli elementi successivi (ovvero sulla seconda metà del dizionario), scartando quelli precedenti; 4. Se tutti gli elementi sono stati scartati: la ricerca termina indicando che il valore non è stato trovato Costo Computazionale Il numero di confronti effettuati dipende da n, ossia dalla lunghezza dell'insieme. Ricerca Binaria ricorsiva Ad ogni chiamata la funzione verifica se l'elemento ricercato si trova al centro dell'intervallo: 1. In caso positivo la funzione termina con successo; 2. In caso negativo si modifica l'intervallo di ricerca e si effettua una nuova chiamata della funzione; 3. Nel caso in cui l'intervallo di ricerca è nullo si termina la ricorsione con insuccesso Ricerca Sequenziale VS Ricerca Binaria Stupid Sort ● L'algoritmo è inefficiente e probabilistico; Funzionamento : 1. L'algoritmo ordina gli elementi di un insieme mescolando gli elementi dell'insieme come se fosse un mazzo di carte; 2. Controlla se è ordinato, se non lo è ricomincia da capo. L'algoritmo arriva quasi sicuramente ad una conclusione per il Teorema della scimmia instancabile secondo il quale : dato un numero illimitato di tentativi, ad ogni tentativo c'è una probabilità di ottenere l'ordinamento giusto quindi, infine dovrebbe avere successo. Il teorema della scimmia instancabile o teorema delle scimmie infinite afferma che : "Una scimmia che preme a caso i tasti di una tastiera per un tempo infinitamente lungo quasi certamente riuscirà a comporre qualsiasi opera letteraria conservata nella Biblioteca Nazionale di Francia" [Borel, 1914]. Il termine scimmia è una metafora per una macchina teorica che produce una sequenza casuale di lettere ad infinito. Costo Computazionale Selection Sort ● E' un algoritmo semplice e di selezione ● L'algoritmo è di tipo non adattivo, ossia il suo tempo di esecuzione non dipende dall'input ma dalla dimensione dell'array Funzionamento : 1. Ricerca ad ogni scansione, l'elemento avente valore minore all'interno della regione del vettore da ordinare; 2. Inserisce il terzo elemento in posizione corretta rispetto a tutti gli altri elementi dell’array; 3. Continua con la procedura fino all'inserimento di tutti gli elementi e quindi finchè non raggiunge l'ordinamento Costo Computazionale L’algoritmo Insertion Sort richiede : ● n-1 confronti se l'insieme è ordinato; ● n^(2) confronti se l'insieme non è ordinato; Shell Sort ● E' un algoritmo di inserimento evoluto; Funzionamento : 1. Confronta tutti gli elementi che si trovano ad una certa distanza d, scambiandoli se non sono ordinati; 2. Riduce di volta in volta il valore di d; 3. Quando d = 1, gli elementi sono ordinati e l'algoritmo si interrompe; Costo Computazionale E' migliore del Bubble sort, Insertion Sort e Selection Sort Quick Sort ● E' un algoritmo evolutivo, di scambio e ricorsivo; Funzionamento : 1. Si divide l'array in due sottoarray e si identifica l'elemento pivot; 2. Gli elementi maggiori del pivot si dispongono a sinistra dell'elemento pivot mentre gli elementi maggiori si dispongono a destra dell'elemento pivot; 3. Dopo la prima divisione dell'array nel sottoarray sinistro e destro, usiamo la tecnica di partizionamento su entrambi i sottoarray sinistro e destro (selezionando un pivot e ripetiamo il processo fino a quando tutti gli elementi sono ordinati nell'elenco dato). Costo Computazionale Complessità temporale : ● O(n log (n)) nel caso migliore e caso medio; ● O(n^2) nel caso peggiore Complessità spaziale : ● O(n*log (n)): log(n) per la partizione e O(n) per attraversare i sotto-array nel caso di array sbilanciati Merge Sort ● E' un algoritmo evolutivo e ricorsivo; Funzionamento : 1. Si individua l'elemento : centrale = (sinistra+destra)/2; 2. Si divide l'array in due sotto-array;