====== Esercitazione 7 ====== Esercizi su funzioni e procedure ricorsive e stdio.h Gli esercizi sono tanti ma arrivate almeno fino al numero 10 (compreso). Quando si ha a che fare con array in funzioni o procedure ricorsive, si possono usare due metodi: *il primo utilizza l'aritmetica dei puntatori per aggiornare ogni volta l'inizio dell'array, *il secondo invece si porta dietro un indice per tenere traccia della posizione raggiunta. Ad ogni modo e' sempre necessario portarsi dietro la dimensione (residua o totale, a seconda del caso). Ricordate che oltre alla funzione o procedura indicata dall'esercizio, si richiede che scriviate anche un main che usi tale funzione e ne dimostri **ogni** funzionalita'. Inoltre, se con l'esercizio viene fornita la firma della funzione/procedura da scrivere, si richiede che la soluzione rispetti questa firma in ogni dettaglio. Ricordate infine che una procedura e' una funzione con tipo di ritorno void. === Esercizio 1 === Scrivere una funzione **ricorsiva** potenza che riceva due interi, base e esponente e ritorni il valore della base elevata alla potenza esponente. int potenza(int base, int esponente); === Esercizio 2 === Scrivere una funzione **ricorsiva** fattoriale che riceva un intero e ritorni il fattoriale di quel valore. int fattoriale(int val); === Esercizio 3 === Scrivere una procedura **ricorsiva** che riceva un array a lo stampi a video. Scrivere la procedura con i due metodi: *con l'aritmetica dei puntatori void stampa1 (int vet[], int dim); *con un indice void stampa2 (int vet[], int i, int dim); === Esercizio 4 === Modificare le procedure **ricorsive** dell'esercizio precedente per stampare l'array in senso inverso. void stampaInverso1 (int vet[], int dim); void stampaInverso2 (int vet[], int i, int dim); === Esercizio 5 su stdio.h === Utilizzare la libreria stdio.h per creare un file misure che contenga 150 numeri interi nell'intervallo (0,20] generati casualmente con la funzione rand(). I numeri devono essere scritti uno per linea separati da '\n'. === Esercizio 6 su stdio.h === Utilizzare il file misure generato nell'esercizio precedente e calcolare il numero di valori generati che ricadono nei 10 intervalli (0, 2] (2,4] ..... (18,20] stampare il numero dei valori per ciascun intervallo sullo standard output. Suggerimento: progettare un ciclo che scorra gli intervalli e per ogni intervallo scorrere il file per trovare il numero dei valori che ricadano nell'intervallo preso in considerazione. === Esercizio 7 su stdio.h === Modificare l' esercizio precedente facendo stampare il numero dei valori per ogni intervallo in fondo al file con i dati. === Esercizio 8 === Scrivere una funzione che calcoli ricorsivamente il numero di elementi pari di un array passato. === Esercizio 9 === Scrivere una funzione **ricorsiva** che controlli che l'array di caratteri passato per argomento sia palindromo. === Esercizio 10 === Scrivere una funzione **ricorsiva** che azzeri tutti gli elementi pari e ritorni il minimo elemento di un array passato. Fare attenzione a memorizzare il valore di ritorno **prima** di modificarlo. === Esercizio 11 === Scrivere una funzione che chieda un valore N all'utente e quindi calcoli ricorsivamente l'N-esimo termine della successione di Fibonacci. F(n) = F(n-1) + F(n-2) === Esercizio 12 === Scrivere una procedura ricorsiva che inverte la porzione di un array individuata dagli indici from e to. void inverti(int v[], int from, int to); === Esercizio 13 === La funzione di Ackermann e' una delle piu' semplici funzioni totalmente computabili a non essere ricorsiva primitiva. http://it.wikipedia.org/wiki/Funzione_di_Ackermann In pratica, la funzione cresce piu' velocemente di qualsiasi funzione ricorsiva primitiva (compreso qualsiasi esponenziale). La funzione e' definita ricorsivamente per casi (sui naturali): *A(m,n) = n+1 (se m=0) * A(m,n) = A(m-1,1) (se m>0 e n=0) *A(m,n) = A(m-1, A(m, n-1)) (se m>0 e n>0) Scrivere una funzione che calcoli la funzione di Ackermann. unsigned long Ackermann(unsigned long m, unsigned long n); Quanto vale Ackermann(3,10)? Quanto vale Ackermann(4,1)? Quanto tempo ci mette a calcolare questi valori? Avvertenza: non andate oltre questi limiti (soprattutto su m) o l'esecuzione potrebbe non terminare in tempo per il fine settimana... === Esercizio 14 === Scrivere una procedura ricorsiva che riceva un array di caratteri e stampi la prima meta' su una riga e la seconda meta' sulla riga sottostante. Se l'array ha un numero dispari di elementi, la lettera centrale dovra' essere stampata su una riga a parte, tra la prima meta' e la seconda meta'. void stampaSuDueRighe(char vet[], int dim) === Esercizio 15 === Riuscite a scrivere la funzione fibonacci ottimizzando (riducendo al minimo) il numero di chiamate ricorsive? *Suggerimento 1: Per verificare quante chiamate vengono eseguite, usate una variabile globale che viene incrementata ad ogni chiamata. *Suggerimento 2: potete sfruttare il fatto che per calcolate F(n-1) dovete sapere F(n-2)? *Suggerimento 3: una funzione in C non puo' ritornare piu' di un valore ma se riceve dei puntatori puo' modificare i valori delle variabili originali. === Esercizio 16 === Scrivere una funzione che ricevuto un array di interi, calcoli e stampi ricorsivamente tutte le permutazioni dell'array.