====== Esercitazione: Array e puntatori ====== ===== Esercizio 1: Funzione swap ===== Scrivere una funzione di prototipo void swap (int *a, int*b); che ha l'effetto di scambiare i valori di due variabili, ad esempio: int a=5; int b=63; swap(&a,&b); printf("a = %d, b = %d \n", a, b); .... deve stampare a = 63, b = 5 Sarebbe stato possibile ottenere lo stesso effetto utilizzando una funzione di prototipo void swap (int a, int b); ? Perche' ? ===== Esercizio 2: Somma e prodotto di matrici ===== Scrivere un programma C costituito da un ''main()'' che legge da standard input due matrici quadrate, le somma, calcola il prodotto e stampa i risultati sullo standard output. ===== Esercizio 3: Ricerca in un array ===== Scrivere una funzione di prototipo int cerca (int * vec, int lung, int x); che cerca se l'elemento ''x'' e' presente nell'array ''vec'' di lung elementi e restituisce 1 se lo trova e 0 se non lo trova. Verificare la correttezza della funzione utilizzando un opportuno ''main()''. ===== Esercizio 4: Generazione di numero casuali in C ===== In alcuni casi e' importante riuscire a generare casualmente dei valori all'intero di programmi C per modellare situazioni reali o per testare opportunamente i programmi scritti. In realta' il computer non riesce a generare eventi realmente "a caso" in quanto tutti i programma si basano su una determinata sequenza di azioni. Tuttavia e' possibile avere un comportamento vicino alla casualita' con le //sequenze pseudocasuali//, che vengono generate con un procedimento deterministico ma mantengono proprieta' statistiche simili a quelle di una vera sequenza casuale. Inoltre le sequenze pseudocasuali possono, su richiesta, rigenerare la stessa sequenza di numeri. Questo e' molto utile ad esempio in fase di testing del codice. La generazione di numeri pseudocasuali e' molto complessa. Tutti i linguaggi di programmazione ad alto livello mettono a disposizione delle opportune funzioni per generare una sequenza. In C, per generare una sequenza pseudocasuale si utilizzano due funzioni di stdlib.h: la funzione void srand(unsigned int seed); che serve a fissare il seme (//seed//) ovvero il valore iniziale della sequenza. E la funzione int rand(void); che genera un intero nell'intervallo ''[0,RAND_MAX]'' ogni volta che viene chiamata. La ''srand()'' deve essere chiamata una sola volta per fissare il seme, successivamente la sequenza puo' essere generata con chiamate successive alla ''rand()''. Partendo dallo stesso valore iniziale si ottiene sempre la stessa sequenza quindi fornendo lo stessp seme a ''srand()'' possiamo riprodurre piu' volte la stessa sequenza casuale quando occorre (per testing o altro). Utilizzare le funzioni ''srand()'' e ''rand()'' per scrivere una funzione di prototipo void init (int * vec, int lung); che inizializza il vettore vec di lunghezza lung con dei valori pseudocasuali nell'intervallo [0,50] (//suggerimento//: leggere attentamente il manuale di ''srand'' e ''rand'' e utilizzare l'operatore resto ''%'') ===== Esercizio 5: MSS, Maximum Segment Sum ===== Dato un array di interi positivi e negativi, il segmento di somma massima e' la porzione contigua dell'array in cui la somma deigli elementi ha valore piu' alto. Ad esempio l'array [2,-4,2,-1,6-3] ha come SSM il segmento [2,-1,6] di valore 7. Si chiede di definire due funzioni per la stampa e per il calcolo di SSM, con i seguenti prototipi : /** stampa l'array s di lunghezza n */ void print_array(int s[], int n); /** calcola SSM sull'array s di lunghezza lung \param s array \param n lunghezza \param s_init puntatore alla variabile che conterra' la posizione di inizio dell'SSM \param s_lung puntatore alla variabile che conterra' la lunghezza del segmento di somma massima \retval k la somma degli elementi dell' SSM */ int ssm (int s[], int n, int * s_init, int * s_lung); ===== Esercizio 6: Invasion Percolation ===== //Invasion percolation// e' una semplice forma frattale basata su un modello di diffusione di fluidi. In due dimensioni, l'invasion percolation si simula come segue. **(Passo 1)** Si genera una griglia quadrata ''sXs'' di numeri casuali nell'intervallo ''[1,r]'' . Ad esempio, una griglia 5x5 di numeri nel range [1,100] puo' essere: 26 17 72 45 38 10 38 39 92 38 44 29 12 29 77 61 26 90 35 11 83 84 18 56 52 **(Passo 2)** poi si marca il centro della griglia come //pieno//, ad esempio '*' indica la cella piena: 26 17 72 45 38 10 38 39 92 38 44 29 * 29 77 61 26 90 35 11 83 84 18 56 52 **(Passo 3)** Si effettua un ciclo in cui ad ogni passo: - si esaminano i 4 vicini di tutte le celle gia' piene (gia' marcate con '*'), - si sceglie la cella con il valore minore, - si marca tale cella come 'piena'. Ad esempio, i quattro vicini della cella (2,2) nella griglia sono: 39 29 * 29 90 L'evoluzione della forma frattale e' : (+ indica la cella selezionata ad ogni nuovo passo) 26 17 72 45 38 10 38 39 92 38 44 + * 29 77 61 26 90 35 11 83 84 18 56 52 26 17 72 45 38 10 38 39 92 38 44 * * 29 77 61 + 90 35 11 83 84 18 56 52 26 17 72 45 38 10 38 39 92 38 44 * * + 77 61 * 90 35 11 83 84 18 56 52 Si richiede di implementare un programma C invocabile da shell con ./percolation che legge dall ostandard input i valori di ''s'' ed ''r'' simula invasion percolation su una griglia sXs con valori nel range [1..r]. Ogni iterazione viene visualizzata sullo schermo. La computazione si ferma quando il 50% delle celle e' stata marcata. Per l'inizializzazione con numeri casuali usare le funzioni ''srand()/rand()'' (vedi esercizio precedente). Per ottenere valori fra 1 ed r basta usare la funzione modulo (%), infatti l'espressione rand()%r + 1 genera ogni volta che viene valutata un numero fra 1 ed r. Per inizializzare il generatore dei numeri casuali con valori diversi (e ottenere quindi sequenze diverse ad ogni run) usare srand(time(NULL)) la ''time()'' restituisce il numero di secondi passati dal 1 gennaio 1970 (includere ''time.h''). Per pulire lo schermo fra una stampa e l'altra si puo' usare system("clear"); per attendere un istante fra le varie visualizzazioni (che altrimenti non sono visibili) si puo' usare sleep(1); che aspetta un secondo, prima di riprendere la computazione (in ''unistd.h''). ===== Esercizio 7: Stampa del triangolo di Tartaglia ===== Il triangolo di Tartaglia รจ una disposizione geometrica dei coefficienti binomiali, ad esempio: 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 ....... Scrivere un programma C che legge un intero ''n'' da standard input e stampa il triangolo di Tartaglia sullo standard output fino all riga ''n''-esima. ===== Esercizio 8: Algoritmi di ordinamento su Array ===== Facendo riferimento agli algoritmi di ordinamento visti a lezione, implementare un algoritmo di ordinamento non ricorsivo (bubblesort o selection sort) e l'algoritmo merge-sort su array di double. Valutare i tempi di esecuzione su array di lunghezza crescente generati casualmente nell'intervallo [0,1] utilizzando le funzioni ''rand(), srand()'' e il comenado di shell ''time''. Ci sono delle variazioni ? ===== Esercizio 9: Algoritmi di ordinamento su Array: costo ... ===== Cercare una formula (approssimata) che fornisca il numero di istruzioni eseguite dai tre algoritmi di ordinamento (selection sort, bubblesort e mergesort) in funzione di //n//, lunghezza dell'array da ordinare.