Esercitazione 7 Procedure e Funzioni Esercizio Scrivere un programma che memorizza in un array di elementi di tipo double le temperature relative al mese corrente e ne determina la temperatura massima, la temperatura minima e la temperatura media. ALGORITMO Scomponiamo il problema nei seguenti sottoproblemi più semplici: ) ) ) ) scrivere una procedura leggitemperature che inizializza un array di double; scrivere una funzione massima che calcola il massimo elemento di un array di double; scrivere una funzione minima che calcola il minimo elemento di un array di double; scrivere una funzione media che calcola il valore medio di un array di double. PROGRAMMA #include <stdio.h> /* procedura che inizializza un array generico di elementi di tipo double con i valori delle temperature inseriti dall’utente */ void leggitemperature (double temperature [ ], int dim) { int i; for (i=0; i<dim; i++) { printf (“inserisci la temperatura del giorno %d” ”, i+1); scanf(“%lf”, &temperature[i]); } } /* fine procedura leggitemperature */ /* procedura che calcola il maggiore di un array generico di double */ double massima (double arr [ ], int n) { int i; double max = arr [0]; for (i=1; i<n; i++) if (arr [i] > max) max = arr [i]; return max; } /* procedura che calcola il minore di un array generico di double */ double minima (double arr [ ], int n) { int i; double min = arr [0]; for (i=1; i<n; i++) if (arr [i] < min) min = arr [i]; return min; } /* procedura che calcola la media di un array generico di double */ double media (double arr [ ], int n) { int i; double media; media = arr[0]; for (i=1; i<n; i++) media += arr[i]; media /= n; return media; } /* funzione principale main */ #define N 31 main ( ) { int n; double max, min, med; double temperature [N]; printf (“TEMPERATURE DEL MESE CORRENTE \n\n”); printf (“Inserisci il numero di giorni del mese corrente: ”); scanf(“%d”, &n); leggitemperature (temperature, n); max = massima (temperature, n); min = minima (temperature, n); med = media (temperature, n); /* invocazione di procedura */ printf (“Massima= %lf, Minima=%lf, Media=%lf\n”, max, min, med);} Esercizio Scrivere una funzione che dato un array di elementi di tipo double contenente i valori delle temperature del mese corrente, restituisce il numero di giorni del mese in cui la temperatura è scesa sotto zero. ALGORITMO Scriviamo una funzione conta_giorni_sotto_zero che, dato un array arr di double e la sua dimensione dim, restituisce il numero di elementi dell’array che hanno valore strettamente minore di 0. /* definizione della funzione conta_giorni_sotto_zero */ int conta_giorni_sotto_zero (double arr [ ], int dim) { int i; int giorni_contati = 0; for (i=0; i<dim; i++) { if (arr [i] < 0) giorni_contati++; } return (giorni_contati); } Esercizio Scrivere una procedura che memorizza in un array i numeri naturali multipli di 3 compresi tra 0 e N (cioè 0+3+6+9+ ...) e ne restituisca la somma. int somma_terzi_numeri (int arr[ ], int dim, int N) { int i, j, somma; i = 0; j = 0; somma = 0; while ((i <= N) && (j<dim)) { arr[j]=i; somma +=arr[j]; i+=3; j++; } return somma; } Le Torri di Hanoi Quello delle Torri di Hanoi è un gioco che si svolge con tre paletti e alcuni dischi di diametro differente con un foro al centro in modo da poter essere infilati nei paletti. Inizialmente i dischi sono tutti impilati a piramide sul primo paletto. Il disco più grande è in basso, il più piccolo in alto. SCOPO DEL GIOCO Lo scopo del gioco è quello di trasferire i dischi dal paletto di sinistra a quello di destra, senza mai mettere un disco su un altro di dimensione più piccola. REGOLE DEL GIOCO ) ) È possibile spostare un solo disco alla volta; tutti i dischi devono essere sempre infilati nei paletti. STRATEGIA La strategia consiste nel considerare uno dei paletti come origine e un altro come destinazione. Il terzo paletto sarà utilizzato come deposito temporaneo. ALGORITMO Supponiamo di avere n dischi, numerati dal più piccolo al più grande. Inizialmente sono tutti impilati nel paletto di sinistra. Il problema di spostare n dischi sul paletto di destra può essere descritto in modo ricorsivo così: ) ) ) Spostare i primi n-1 dischi dal paletto di sinistra a quello di centro. Spostare il disco n-esimo (il più grande) sul paletto di destra. Spostare i rimanenti n-1 dischi dal paletto di centro a quello di destra. In questo modo il problema può essere risolto per qualsiasi valore di n>0 (n=0 è la condizione di stop della ricorsione). PROGRAMMA Per programmare questo gioco indichiamo ) ) ) il primo paletto (quello di sinistra) con L il secondo paletto (quello di centro) con C il terzo paletto (quello di destra) con R Definiamo la procedura ricorsiva transfer, che trasferisce n dischi da un paletto all’altro. void transfer (int n, char from, char to, char temp) { /* n indica il numero di dischi che si vuole trasferire, from indica il paletto di origine, to indica il paletto di arrivo e temp indica il paletto che viene usato per la sosta temporanea */ if (n > 0) { /* sposta n-1 dischi dall’origine alla sosta temporanea */ transfer (n-1, from, temp, to); /* sposta il disco n-esimo dall’origine alla destinazione */ printf (“Sposta il disco %d da %c a %c\n”, n, from, to); /* sposta n-1 dischi dalla sosta temporanea alla destinazione*/ transfer (n-1, temp, to, from); } return; } /* programma principale per il gioco delle TORRI DI HANOI */ /* realizzato con una procedura ricorsiva */ #include <stdio.h> void transfer (int n, char from, char to, char temp); main ( ) { int n; printf (“Benvenuto nelle TORRI DI HANOI\n\n”); printf (“Quanti dischi ? ”); scanf (“%d”, &n); transfer (n, ‘L’, ‘R’, ‘C’); } Eseguendo il programma con n=3 si otterrà il seguente output: Benvenuto nelle TORRI DI HANOI Quanti dischi ? 3 Sposta il disco 1 da L a R Sposta il disco 2 da L a C Sposta il disco 1 da R a C Sposta il disco 3 da L a R Sposta il disco 1 da C a L Sposta il disco 2 da C a R Sposta il disco 1 da L a R Esercizio Scrivere una funzione ricorsiva che calcoli la somma degli interi pari tra 2 e N PROGRAMMA int SommaPari (int N) { if (N<2) return 0; else if (( N%2) == 0) return N + SommaPari (N-2); else return SommaPari (N-1); } ESERCIZIO Si consideri la seguente funzione F la cui specifica è data in modo ricorsivo (si supponga N intero): F(N) = restituisce 1 se N <= 0, -1+4*F(N-1) + F(N-2), altrimenti. Si scriva la funzione C che realizzerebbe tale specifica SOLUZIONE: int F(int N) { if (N<=0) return 1 else return -1+4*F(N-1) + F(N-2); } Esercizio Scrivere una procedura ricorsiva che, dato un array di interi di lunghezza n, calcoli la somma dei suoi elementi. Esempio int a[1]; somma_ricorsiva(a, 1)=a[0]; int a[6]; somma_ricorsiva(a, 6)=somma_ricorsiva(a, 5) + a[5]; 0 1 2 3 4 5 Soluzione 1 #include <stdio.h> #define DIM 10 int somma_ricorsiva (int a[ ], int dim) { if (dim == 1) return a[0]; else return somma_ricorsiva (a, dim-1) + a[dim-1]; } main ( ) { int sum; int mio_array [DIM]; inizializza_array (mio_array, DIM); /*supponiamo che questa procedura sia stata definita*/ sum = somma_ricorsiva (mio_array, DIM); } Un’altra soluzione Esempio int a[1]; somma_ricorsiva(a, 0, 0)=a[0]; int a[6]; somma_ricorsiva(a, 0, 5)=a[0] + somma_ricorsiva(a, 1, 5); 0 1 inf inf+1 2 3 4 5 sup Soluzione 2 #include <stdio.h> #define DIM 10 int somma_ricorsiva (int a[ ], int inf, int sup) { if (inf == sup) return a[inf]; else return a[inf] + somma_ricorsiva (a, inf+1, sup); } main ( ) { int sum; int mio_array [DIM]; inizializza_array (mio_array, DIM); sum = somma_ricorsiva (mio_array, 0, DIM-1); } Inversione di una sequenza di caratteri Scrivere un programma che legge una sequenza di caratteri terminata da \n in ingresso e la stampa invertita usando prima una funzione iterativa void invertiInputIterativa (void) e poi una funzione ricorsiva void invertiInputRicorsiva (void). Si usino le funzioni getchar e putchar. #include <stdio.h> #define LUNGMAX 10 void invertiInputIterativa (void) /* Inverte una sequenza di caratteri letti in input. Versione iterativa */ { char parola[LUNGMAX]; int lung = 0; int i; char ch; ch = getchar(); while (ch != '\n' && lung < LUNGMAX){ /* lettura e memorizzazione in un array */ parola[lung] = ch; lung++; ch = getchar(); } for (i = lung-1; i >= 0; i--) /* stampa della sequenza invertita */ putchar(parola[i]); } void invertiInputRicorsiva (void) /* Inverte una sequenza di caratteri letti in input. Versione ricorsiva */ { char ch; ch = getchar(); if (ch != '\n') { invertiInputRicorsiva(); putchar(ch); } } /* chiamata ricorsiva */ /* al ritorno dalla chiamata ricorsiva viene stampato il carattere letto */ int main(void) { printf("Immetti una sequenza di caratteri (lunga al piu' %d)!\n", LUNGMAX); invertiInputIterativa(); printf("\n Immetti una sequenza di caratteri (di lunghezza qualsiasi)!\n"); invertiInputRicorsiva(); putchar('\n'); }