Programmazione a Oggetti e JAVA. Prof. B.Buttarazzi A.A. 2012/2013

Documenti analoghi
Fondamenti di Informatica - 1. Prof. B.Buttarazzi A.A. 2011/2012

n n 1 n = > Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita

La ricorsione. Ver Claudio Fornaro - Corso di programmazione in C

public static boolean occorre (int[] a, int n) { int i = 0; boolean trovato = false;

Corso: Fondamenti di Informatica (Gruppo 2) a.a Corsi di laurea: Ing. Settore Informazione

Definizione di metodi in Java

7 - Programmazione procedurale: Dichiarazione e chiamata di metodi ausiliari

Esercizi riassuntivi (Fondamenti di Informatica 2 Walter Didimo) Soluzioni

Metodi statici. Dichiarazione e chiamata di metodi statici

Esercizio 2 (punti 7) Dato il seguente programma C: #include <stdio.h> int swap(int * nome, int length);

Algebra di Boole: Concetti di base. E un algebra basata su tre operazioni logiche

FUNZIONI RICORSIVE PROGRAMMAZIONE RICORSIVA: Esempi di problemi ricorsivi:

Roadmap. Ricorsione: funzioni ricorsive. Definizione di fattoriale. Definizione dei numeri Fibonacci

Funzioni, Stack e Visibilità delle Variabili in C

19 - Eccezioni. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Costrutti iterativi. Utilizzo dei costrutti iterativi

ERRATA CORRIGE. void SvuotaBuffer(void); void SvuotaBuffer(void) { if(getchar()!=10) {svuotabuffer();} }

DIPARTIMENTO DI ELETTRONICA, INFORMAZIONE E BIOINGEGNERIA. INFORMATICA B Ingegneria Elettrica. La ricorsione

Laboratorio di Informatica

Corso sul linguaggio Java

Programmazione 1 A.A. 2015/2016

Fondamenti di Informatica 6. Algoritmi e pseudocodifica

Laboratorio di Python

Compitino di Laboratorio di Informatica CdL in Matematica 13/11/2007 Teoria Compito A

Studio delle successioni con il software

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

Programmazione. Cognome... Nome... Matricola... Prova scritta del 22 settembre Negli esercizi proposti si utilizzano le seguenti classi:

Rappresentazione degli algoritmi

INFORMATICA DI BASE Linguaggio C Prof. Andrea Borghesan

Un tipico esempio è la definizione del fattoriale n! di un numero n, la cui definizione è la seguente:

Fondamenti di Informatica T. Linguaggio C: Stack e Ricorsione

Esempio : i numeri di Fibonacci

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1

Laboratorio di Programmazione 1 [Java]

3 Costrutti while, for e switch

Algoritmi di Ricerca. Esempi di programmi Java

Programmazione Orientata agli Oggetti in Linguaggio Java

Definizione di classi. Walter Didimo

Ricorsione. Emilio Di Giacomo e Walter Didimo

Algoritmi di Ricerca. Esempi di programmi Java

PROGRAMMAZIONE STRUTTURATA

Programmazione Orientata agli Oggetti. Emilio Di Giacomo e Walter Didimo

Laboratorio di Programmazione: Linguaggio C Lezione 9 del 27 novembre 2013

IL LINGUAGGIO JAVA Input, Tipi Elementari e Istruzione Condizionale

Informatica/ Ing. Meccanica/ Prof. Verdicchio/ 14/02/2012 / Foglio delle domande / VERSIONE 1

Introduzione al C. Esercitazione 6. Raffaele Nicolussi. Corso di Fondamenti di Informatica Ingegneria Clinica

Classi e array. Viene ora affrontato un problema di definizione di una classe in cui una variabile d istanza è di tipo array

Tempo e spazio di calcolo (continua)

Programmazione. Cognome... Nome... Matricola... Prova scritta del 11 luglio 2014

Le Funzioni e la Ricorsione

Laboratorio di Programmazione Lezione 2. Cristian Del Fabbro

Fondamenti di Informatica T-1 Modulo 2

Compito di Programmazione, 22 marzo 2007 INFORMATICI E MULTIMEDIALI

Le basi del linguaggio Java

Una funzione è detta ricorsiva se chiama, direttamente o indirettamente, se stessa. In C tutte le funzioni possono essere usate ricorsivamente.

Lezione 6 programmazione in Java

Le strutture di controllo in C++

Programmazione Java Struttura di una classe, Costruttore, Riferimento this

UNIVERSITÀ DEGLI STUDI DI PAVIA FACOLTÀ DI INGEGNERIA. Matlab: esempi ed esercizi

STRUTTURE DI CONTROLLO DEL C++

Programmazione Ricorsione

Corso di Laurea Ingegneria Civile Fondamenti di Informatica. Esercizi sui metodi. Carla Limongelli. Maggio Esercizi 1

Esempi di Problemi Iterativi

Programmazione in Java (I modulo)

21 - Alberi e Ricorsione

Laboratorio di Programmazione M-Z

9 - Array. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Transcript:

Programmazione a Oggetti e JAVA Prof. B.Buttarazzi A.A. 2012/2013

Sommario La ricorsione Metodi ricorsivi Esercizi proposti 16/01/2013 2

La ricorsione In Java ogni metodo può chiamare anche se stesso, secondo una tecnica detta ricorsione. Ovviamente tali metodi devono sempre contenere un istruzione di controllo che ha il compito di interrompere la successione delle chiamate, se si verificano certe condizioni. 3

Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita n! 1 n( n 1)! se se n n 0 0 dove n è un numero intero non negativo 4.11.2004 4

Confronto fra definizione iterativa e ricorsiva Funzione non ricorsiva n!= 1*2*3*...*(n-1)*n fatt(n)= 1*2*3*...*(n-1)*n; Funzione ricorsiva 0!=1 n!= n*(n-1)!; fatt(n)=n*fatt(n-1) 5

Il calcolo del fattoriale Vediamo di chiarirne il significato 0! = 1 1! = 1(1-1)! = 1 0! = 1 1 = 1 2! = 2(2-1)! = 2 1! = 2 1 = 2 3! = 3(3-1)! = 3 2! = 3 2 1 = 6 4! = 4(4-1)! = 4 3! = 4 3 2 1 = 24 5! = 5(5-1)! = 5 4! = 5 4 3 2 1 = 120 Quindi, per ogni n intero positivo, il fattoriale di n è il prodotto dei primi n numeri interi positivi

Il calcolo del fattoriale Per implementare la funzione per il calcolo del fattoriale con un metodo statico iterativo siamo costretti a fare un analisi della definizione per scrivere l algoritmo 7

Il calcolo del fattoriale Per implementare la funzione per il calcolo del fattoriale con un metodo statico iterativo siamo costretti a fare un analisi della definizione per scrivere l algoritmo: public static float fattoriale (int n) { float F=1; int i=1; do { F=F*i; i=i+1; } while (i<=n); return F; 8

Il calcolo del fattoriale Implementando direttamente la definizione ricorsiva, è naturale scrivere: { public static float fattoriale (int n) } float f; if (n == 0) f = 1; else f = n * fattoriale(n - 1); return f;

Il calcolo del fattoriale Implementando direttamente la definizione ricorsiva, è naturale scrivere: { public static float fattoriale (int n) float f; if (n == 0) f = 1; else f = n * fattoriale(n - 1); return f; } Questa soluzione si basa sulla invocazione di un metodo mentre si esegue il metodo stesso! Questa possibilità è permessa in tutti i linguaggi di programmazione che ammettono la ricorsione

Il calcolo del fattoriale La funzione ricorsiva fattoriale non necessita di iterazioni, ma include internamente il calcolo del risultato, infatti restituisce 1 se il parametro ricevuto uguale a 0 mentre in caso contrario il valore restituito è il prodotto di n per il fattoriale (n-1), pertanto fattoriale calcola il valore da restituire chiamando se stessa e "passandosi" come parametro il parametro appena ricevuto, diminuito di uno. { public static float fattoriale (int n) float f; if (n == 0) f = 1; else f = n * fattoriale(n - 1); return f; } Questa soluzione si basa sul fatto invocare un metodo mentre si esegue il metodo stesso! Questa possibilità è lecito in tutti i linguaggi di programmazione che ammettono la ricorsione

La ricorsione Per capire come utilizzare correttamente la ricorsione, vediamo innanzitutto come funziona. Quando un metodo ricorsivo invoca se stesso, la macchina virtuale Java esegue le stesse azioni che vengono eseguite quando viene invocato un metodo qualsiasi sospende l esecuzione del metodo invocante (le variabili locali rimangono congelate) esegue il metodo invocato fino alla sua terminazione (con nuove variabili locali e passando i parametri per valore) riprende l esecuzione del metodo invocante dal punto in cui era stata sospesa (recuperando le variabili locali) 4.11.2004 12

La ricorsione Vediamo la sequenza delle istruzioni per calcolare 3! si invoca f(3) f(3) lascia in sospeso il calcolo 3* f(2) e invoca f(2) f(2) lascia in sospeso il calcolo 2* f(1) invoca f(1) f(1) lascia in sospeso il calcolo 1* f(0) e invoca f(0) f(0) restituisce 1 a f(1) f(1) calcola1*1 e restituisce 1 a f(2) f(2) calcola 2*1 e restituisce 2 a f(3) f(3) calcola 3*2 e restituisce 6 al chiamante Si crea quindi una pila ( stack) di metodi in attesa, ciascuno con le sue variabili locali, che si allunga e che poi si accorcia fino ad esaurirsi

La ricorsione Invocare un metodo mentre si esegue lo stesso metodo è un paradigma di programmazione che si chiama ricorsione e un metodo che ne faccia uso si chiama metodo ricorsivo La ricorsione è uno strumento molto potente per realizzare alcuni algoritmi (ma è anche fonte di errori di difficile diagnosi) Esistono infatti due regole ben definite (passo base e passo ricorsivo) che vanno utilizzate per scrivere metodi ricorsivi che funzionino 4.11.2004 14

Prima regola La ricorsione: passo base il metodo ricorsivo deve fornire la soluzione del problema in almeno un caso particolare, senza ricorrere ad una chiamata ricorsiva tale caso si chiama caso base della ricorsione nel nostro esempio, il caso base era if (n == 0) return 1; a volte ci sono più casi base, non è necessario che il caso base sia unico 4.11.2004 15

Seconda regola La ricorsione: passo ricorsivo il metodo ricorsivo deve effettuare la chiamata ricorsiva dopo aver semplificato il problema nel nostro esempio, per il calcolo del fattoriale di n si invoca la funzione ricorsivamente per conoscere il fattoriale di n-1, cioè per risolvere un problema più semplice f = n * fattoriale(n - 1); il concetto di problema più semplice varia di volta in volta: in generale, bisogna avvicinarsi ad un caso base 4.11.2004 16

Ricorsione infinita Si noti quindi che non tutti i metodi ricorsivi realizzano algoritmi! se manca il caso base, il metodo ricorsivo continua ad invocare se stesso all infinito se il problema non viene semplificato ad ogni invocazione ricorsiva, il metodo ricorsivo continua ad invocare se stesso all infinito Dato che la lista dei metodi in attesa si allunga indefinitamente, l ambiente runtime esaurisce la memoria disponibile per tenere traccia di questa lista, e il programma termina con un errore. 4.11.2004 17

Le regole appena viste Ricorsione infinita implicano che ad ogni invocazione il problema diventi più semplice avvicinandosi sempre più al caso base che non richiede ricorsione ovvero che per quanto complesso possa essere il problema la soluzione sia calcolata in un numero finito di passi 4.11.2004 18

Esercizio

Vediamo la codifica di tale funzione in modo iterativo /* algoritmo iterativo */ public static long iterfibonacci(int n){ if(n<=1) return n; long x=0; long y=1; long tmp; for(int i=2; i<=n; i++){ tmp = x; x = y; y = tmp+x; // dopo l'i-esima iterazione: x=f(i-1), y=f(i) } return y; }} Vediamo come si semplifica la soluzione ricorsiva

public static float fibo (int n) { } float fib; if (n == 0) { fib = 0; } else if (n == 1) { fib = 1; } else { fib = fibo(n-1)+ fibo(n-2); } return fib;

public static float fib (int n) { { if (n < 2) { return n; } else { return fib(n-1)+fib(n-2); } } }

.osservazioni La semplicità del codice ha un costo che studieremo quando parleremo di complessità per il momento basta osservare che ad ogni chiamata vengono genereate 2 variabili quindi si occupa più memoria.

Esercizi Scrivere un metodo statico ricorsivo per il calcolo della funzione esponenziale definita come segue: 16/01/2013 24

Esercizi Scrivere un metodo statico ricorsivo per il calcolo della funzione esponenziale definita come segue: 16/01/2013 25

Esercizi Scrivere un metodo statico che, dati un array di interi a ed un intero n, restituisce il numero delle occorrenze di n in a 16/01/2013 26

Esercizi Scrivere un metodo statico che, dati un array di interi a ed un intero n, restituisce la posizione della prima occorrenza di n in a, e -1 se n non compare in a. 16/01/2013 27

Esercizi Scrivere un metodo statico che, dati un array di interi a ed un intero n, restituisce true se n compare in a, false altrimenti. 16/01/2013 28

Esercizi Scrivere un metodo statico che, dati un array bidimensionale di interi a ed un intero n, restituisce true se n compare in a, false altrimenti. 16/01/2013 29

Esercizi Scrivere un metodo statico che dato un array di interi restituisca true se tutti i suoi elementi sono identici, e false altrimenti. 16/01/2013 30

Esercizi Scrivere un metodo che, dati un array bidimensionale di interi a e due interi k ed n, restituisce true se in ogni riga a[i] di a esistono almeno k elementi maggiori di n, altrimenti il metodo restituisce false. 16/01/2013 31

Cosa abbiamo imparato? Come funziona la ricorsione: il processo secondo il quale un metodo può anche richiamare se stesso; Che cos è un metodo ricorsivo: ossia un metodo che fa uso della ricorsione; Che cos è la ricorsione infinita. 16/01/2013 32

Questionario 1)Quali dei seguenti programmi è errato per calcolare il fattoriale di un numero in Java? class Fattoriale { static float fatt(int x) { int i; float f=1; do{ f=f*i; i= i+1; } while(i<=x); return f; }; class Fattoriale { static int fatt(int x) { int i; int f=1; for(i=1; i<=x; i=i+1) { f=f*i; } return f; }; 16/01/2013 33

public class Fattoriale { public static void main(string[] args) { int n, i; long fatt; if (args.length > 0) { n = Integer.parseInt(args[0]);} else { n = MyUtility.readInt("Inserisci N: ");} fatt = 1; for (i = 1; i <= n; i++) { fatt *= i;} System.out.println(n+"! = "+fatt);} }; class Fattoriale { static float fatt(float x) { int i; int f=1; for(i=1; i<=x; i=i+1) { f=f*i;} return f; }; 16/01/2013 34

2)A cosa serve la ricorsione? Ad invocare un metodo di un altra classe; Ad eseguire un metodo uno dopo l altro; Ad invocare un metodo dopo che il metodo stesso è stato eseguito; Ad invocare un metodo mentre si esegue lo stesso metodo. 3)Quali delle seguenti non è un azione che esegue la JVM quando viene invocato un metodo ricorsivo? Sospendere l esecuzione del metodo invocante; Eseguire il metodo invocato fino alla sua terminazione recuperando le variabili locali; Riprendere l esecuzione del metodo chiamante dal punto in cui era stato sospeso; Eseguire il metodo invocato fino alla sua terminazione. 4) Nei programmi scritti nella domanda 1 è presente almeno un passo ricorsivo? Si in tutti i 4 programmi; No in nessuno dei 4 programmi; Solo nel secondo programma; Solo nel terzo programma. 5) Nei programmi scritti nella domanda 1 è presente almeno un caso base? Si in tutti i 4 programmi; No in nessuno dei 4 programmi; Solo nel secondo programma; Solo nel terzo programma. 16/01/2013 35

6)Quali sono le regole che bisogna seguire per scrivere un metodo ricorsivo? Il metodo deve fornire la soluzione del problema in almeno un caso particolare, e deve effettuare la chiamata ricorsiva dopo aver semplificato il problema; Il metodo deve fornire la soluzione del problema in almeno un caso particolare, ricorrendo ad una chiamata ricorsiva e deve effettuare di nuovo la chiamata dopo aver semplificato il problema; Il metodo deve fornire la soluzione del problema in più di un caso particolare, e deve effettuare la chiamata ricorsiva dopo aver semplificato il problema; Il metodo deve semplificare il problema e deve poi effettuare la chiamata ricorsiva. 7)Quale delle seguenti affermazioni sulla ricorsione è esatta? Ad ogni invocazione del metodo il problema diventa sempre più complesso; Anche la soluzione del caso base richiede l uso della ricorsione; Bisogna effettuare la chiamata ricorsiva dopo aver semplificato il problema; Il passo ricorsivo non può essere messo all interno di un espressione. 8)In quale caso non si ha ricorsione infinita? Se il problema viene semplificato ad ogni invocazione ricorsiva; Se manca il caso base; Se il problema non viene semplificato ad ogni invocazione ricorsiva; Se il problema viene semplificato solo alla prima invocazione ricorsiva. 16/01/2013 36

9)Quale delle seguenti è un esempio di funzione ricorsiva? n!=1*2*3* *(n-1)*n; fatt(n)=n*fatt(n-1); fatt(n)= 1*2*3*...*(n-1)*n; 3!=6. 10)Quali dei seguenti programmi non è corretto per calcolare la sequenza di Fibonacci in maniera ricorsiva? class Fibonacci { public static long fibo(long n) { if(n<=1) return n; else return fibo(n-1)+ fibo(n-2); } }; class Fibonacci { public static long fibo(long n) { if(n<=1) return n; else return fibo(n-1)+ fibo(n-2);} public static void main(string args[]) { long n = Integer.parseInt(args[0]); System.out.println("fib(" + n + ")=" + fibo(n));} }; 16/01/2013 37

class Fibonacci { public static long fibo(long n) { long fibn_1 = 0, fibn_2 = 1, fibn=1; if(n<=1) return n; else { for(int i=2; i<=n; i++) { fibn=fibn_1+fibn_2; fibn_1=fibn_2; fibn_2=fibn; } return fibn; } } }; class Fibonacci { public static long fibo(int n) { if(n<=1) return n; else return fibo(n-1)+ fibo(n-2);} }. 11)Nei programmi della domanda 10 è presente almeno un caso base? Si in tutti i 4 programmi; No in nessuno dei 4 programmi; Si nel secondo e nel terzo programma; Si nel primo e nell ultimo; Si in tutti tranne nel terzo; Si in tutti ad eccezione del primo. 16/01/2013 38

12)Nel terzo programma della domanda 10 qual è il caso base? return n; return fibn; if(n<=1) return n; for(int i=2; i<=n; i++) { fibn=fibn_1+fibn_2; fibn_1=fibn_2; fibn_2=fibn; } return fibn. 13) Nei programmi della domanda 10 è presente un passo ricorsivo? Si in tutti i 4 programmi; No in nessuno dei 4 programmi; Si nel secondo e nel terzo programma; Si nel primo e nell ultimo; Si in tutti tranne nel terzo; Si in tutti ad eccezione del primo. 14) Qual è il passo ricorsivo presente nel secondo programma della domanda 10? return fibo(n-1)+ fibo(n-2); fibo(n-1)+ fibo(n-2); long n = Integer.parseInt(args[0]); System.out.println("fib(" + n + ")=" + fibo(n));; if(n<=1) return n; else return fibo(n-1)+ fibo(n-2);. 16/01/2013 39

15) Quali delle seguenti opzioni è corretta per dichiarare un metodo media() che dispone di un tipo restituito double e due parametri interi x e y? double media(x, y) { ; double media( int x, int y) { ; double Media( int x, int y) { ; public double Media(x, y) { ; 16) Per lo studio di quali funzioni può essere utilizzato il metodo della ricorsione? Per il calcolo del fattoriale; Per il calcolo del fattoriale e per la sequenza di Fibonacci; Per il calcolo delle funzioni goniometriche; Per il calcolo del fattoriale, per la sequenza di Fibonacci e per le funzioni goniometriche. 16/01/2013 40

Esercizio Scrivere una programma Java che realizza il gioco indovina che numero ho pensato, descritto come segue: inizialmente, il programma genera un numero casuale intero compreso tra 1 e 100 e lo sceglie, e poi chiede all utente di indovinare il numero scelto dopo ciascun tentativo di risposta dell utente, l applicazione deve segnalare se la risposta data è giusta, oppure il numero è maggiore oppure il numero è minore rispetto al numero scelto il programma deve continuare a chiedere numeri all utente fino a che questi non abbia dato la risposta corretta, oppure abbia scelto di rinunciare ad indovinare (digitando il numero 0) se l utente indovina il numero scelto, il programma deve congratularsi con l utente, visualizzando anche il numero di tentativi fatti dall utente 16/01/2013 41

Ad esempio, se il numero scelto dal programma fosse 21, l interazione tra applicazione e utente potrebbe essere la seguente Ho pensato un numero intero compreso tra 1 e 100. Indovina che numero ho pensato: 40 40 è troppo alto. Indovina che numero ho pensato: 30 30 è troppo alto. Indovina che numero ho pensato: 20 20 è troppo basso. Indovina che numero ho pensato: 22 22 è troppo alto. Indovina che numero ho pensato: 21 Bravo! Hai indovinato facendo 5 tentativi! 16/01/2013 42