Ricorsione. (da lucidi di Marco Benedetti)

Documenti analoghi
AA LA RICORSIONE

Il principio di induzione e i numeri naturali.

La ricorsione. Politecnico di Milano Sede di Cremona

Ricorsione. Corso di Fondamenti di Informatica

Matematica generale CTF

Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi.

Permutazione degli elementi di una lista

x u v(p(x, fx) q(u, v)), e poi

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

Intelligenza Artificiale

Ottimizzazione Multi Obiettivo

Programmazione I - Laboratorio

void funzioneprova() { int x=2; cout<<"dentro la funzione x="<<x<<endl; }

RICORSIVITA. Vediamo come si programma la soluzione ricorsiva al problema precedente: Poniamo S 1 =1 S 2 =1+2 S 3 =1+2+3

Valutazione delle Prestazioni. Valutazione delle Prestazioni. Architetture dei Calcolatori (Lettere. Tempo di risposta e throughput

DAL PROBLEMA ALL'ALGORITMO AL PROGRAMMA SCRITTO IN Come. Scopo principale dell informatica è risolvere problemi con i calcolatori.

Corso di Informatica

Esercitazione 7. Procedure e Funzioni

Ricorsione. Rosario Culmone. - p. 1/13

Informatica 3. Informatica 3. LEZIONE 10: Introduzione agli algoritmi e alle strutture dati. Lezione 10 - Modulo 1. Importanza delle strutture dati

2 Progetto e realizzazione di funzioni ricorsive

I SISTEMI DI NUMERAZIONE

Esercizi di Calcolo delle Probabilita (I)

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI

LEZIONE: Pensiero Computazionale. Tempo della lezione: Minuti. - Tempo di preparazione: 15 Minuti.

Il sistema monetario

Monitor. Introduzione. Struttura di un TDA Monitor

Gli input sono detti anche fattori di produzione: terra, capitale, lavoro, materie prime.

Informatica per la comunicazione" - lezione 8 -

SISTEMI DI NUMERAZIONE IL SISTEMA DECIMALE

Matematica e giochi di gruppo

Esponenziali elogaritmi

Equilibrio bayesiano perfetto. Giochi di segnalazione

Introduzione al MATLAB c Parte 2

RAPPRESENTAZIONE GRAFICA DEGLI ALGORITMI

Lezione 8. La macchina universale

La somma. Esempio: Il prodotto. Esempio:

Introduzione agli Abstract Data Type (ADT)

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Anno 3. Funzioni: dominio, codominio e campo di esistenza

Corso di Fondamenti di Informatica Algoritmi su array / 2

Fondamenti dei linguaggi di programmazione

Teoria delle code. Sistemi stazionari: M/M/1 M/M/1/K M/M/S

Tecniche avanzate di sintesi di algoritmi: Programmazione dinamica Algoritmi greedy

Programmazione dinamica

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

LANCIAMO UN DADO PER DECIDERE CHI DEVE INIZIARE IL GIOCO. PARTIRA IL NUMERO PIU ALTO

Algoritmi e strutture dati. Codici di Huffman

Forze come grandezze vettoriali

Problema del trasporto

SOMMARIO Coda (queue): QUEUE. QUEUE : specifica QUEUE

COGNOME E NOME (IN STAMPATELLO) MATRICOLA

Laboratorio di Algoritmi e Strutture Dati

Sistemi Informativi Territoriali. Map Algebra

Algoritmi su array / 2

Laboratorio di programmazione

Indice. 1 Introduzione alle Equazioni Differenziali Esempio introduttivo Nomenclatura e Teoremi di Esistenza ed Unicità...

Corso di Laurea in Scienze della Formazione Primaria Università di Genova MATEMATICA Il

I sistemi di numerazione

SCHEDA DI RECUPERO SUI NUMERI RELATIVI

da 2 a 5 giocatori, dai 10 anni in su, durata 30 minuti

Informatica 3. LEZIONE 7: Fondamenti di programmazione orientata agli oggetti (1)

Il presente documento viene redatto da Career Counseling con lo scopo finale di avere una visione dell andamento del MdL, in modo da poter

2. Spiegare brevemente qual è la funzione del compilatore e la sua importanza per il programmatore.

Librerie digitali. Video. Gestione di video. Caratteristiche dei video. Video. Metadati associati ai video. Metadati associati ai video

Obiettivi dell esercitazione. Requisiti (cont.) Requisiti. Università di Roma La Sapienza A.A Facoltà di Ingegneria Sede di Latina

Funzioni in C. Violetta Lonati

Verifica della correttezza formale del numero di partita IVA

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

L acquisto della cittadinanza italiana

Fasi di creazione di un programma

Soluzione dell esercizio del 12 Febbraio 2004

1. PRIME PROPRIETÀ 2

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

Introduzione alla teoria dei database relazionali. Come progettare un database

Il calcolo letterale per risolvere problemi e per dimostrare

Collegamento a terra degli impianti elettrici

Esercizi su. Funzioni

Transitori del primo ordine

Come creare il test di Cooper tramite l applicazione Training Center

Appunti sulla Macchina di Turing. Macchina di Turing

La selezione binaria

SISTEMI DI NUMERAZIONE E CODICI

Deadlock e Starvation

ARCHIVIA PLUS - ARCHIFILE

Kangourou della Matematica 2014 finale nazionale italiana Mirabilandia, 12 maggio 2014

Utilizzo delle formule in Excel

Comparatori. Comparatori di uguaglianza

Spiegazione Open Interest Storico:

Alla ricerca dell algoritmo. Scoprire e formalizzare algoritmi.

Le equazioni. Diapositive riassemblate e rielaborate da prof. Antonio Manca da materiali offerti dalla rete.

Funzioni funzione dominio codominio legge argomento variabile indipendente variabile dipendente

Programmazione Pubblica/Mercato

Macroeconomia, Esercitazione 6. 1 Esercizi. 1.1 Taylor rule e Domanda Aggregata Dinamica/ Taylor rule e Domanda Aggregata Dinamica/2

Da dove nasce l idea dei video

1 Giochi a due, con informazione perfetta e somma zero

Computational Game Theory

ISTITUTO COMPRENSIVO DI PAGNACCO SCUOLA ELEMENTARE DE AMICIS PROGETTO SeT. Scheda di lavoro. Problemi procedurali NONSOLOCALCOLO

9. Urti e conservazione della quantità di moto.

Transcript:

Ricorsione (da lucidi di Marco Benedetti)

Funzioni ricorsive Dal punto di vista sintattico, siamo in presenza di una funzione ricorsiva quando all interno della definizione di una funzione compaiono una o più invocazioni alla funzione che si sta definendo; in altre parole, la funzione ricorre a se stessa per svolgere il proprio compito; Questo tipo di ricorsione è chiamata ricorsione diretta; esistono casi più complessi, come quello in cui nel corpo della funzione f 1 si invoca la funzione f 2 e al tempo stesso nel corpo di f 2 si invoca la funzione f 1 (si parla in questo caso di mutua ricorsione); esistono tipi di ricorsione ancora più generali, ma in questa lezione ci limitiamo alla ricorsione semplice; Le funzioni ricorsive non sono -come potrebbe sembrare- condannate a non terminare mai, perchè l invocazione ricorsiva (o, brevemente: ricorsione) non avviene incondizionatamente; ci devono essere, al contrario, dei casi in cui la funzione spezza la catena della ricorsione e riesce a calcolare il risultato che le è richiesto senza ulteriori invocazioni ricorsive; Le funzioni ricorsive risultano estremamente comode nella codifica di tutti gli algoritmi modellati su un procedimento di soluzione induttivo.

Formulazioni induttive Una soluzione induttiva ad un problema è caratterizzata dall individuazione di una dimensione lungo la quale il problema può essere semplificato/ridotto/rimpiccolito; lungo tale dimensione si incontrano quindi istanze più piccole - cioè più semplici - dello stesso problema; Una volta individuata la dimensione lungo la quale muoversi, si specificano i due seguenti passi fondamentali: il caso base, cioè la classe di istanze sufficientemente piccole (quindi sifficientemente semplici) da poter essere risolte in maniera diretta (senza ricorsione); il caso induttivo, cioè la classe delle istanze restanti che - pur non essendo direttamente risolvibili - si prestano ad essere risolte tramite un procedimento di questo tipo: 1. si estrapolano/estraggono/deducono dall istanza in considerazione una o più istanze dello stesso problema che risultano più piccole di quella di partenza; 2. si suppone di saper risolvere direttamente tali istanze (in realtà: si applica ricorsivamente il procedimento che si sta definendo); 3. si compongono in qualche modo le soluzioni a tali istanze e si fanno i calcoli opportuni per ottenere la soluzione dell istanza di partenza.

Implementazioni ricorsive Una volta descritto in maniera induttiva il procedimento di soluzione di un problema, la sua implementazione ricorsiva in C++ ricalca in genere il seguente schema: SOLUZIONE funzione_ricorsiva (PROBLEMA p, altri parametri ) { if (siamo nel caso base) { risolvi direttamente il problema p: sia sol la soluzione; return sol; } else { //siamo nel caso induttivo estrai da p uno o più sottoproblemi p i di dimensione minore di p; per ogni i, sia: s i = funzione_ricorsiva(p i, altri parametri ); } } componi le soluzioni s i ed effettua gli altri calcoli necessari ad ottenere una soluzione sol del problema p; return sol;

Elementi delle funzioni ricorsive Dallo schema descritto si intuisce come le funzioni ricorsive possano garantire la terminazione: ogni volta che una funzione invoca se stessa, sta richiedendo la soluzione di un problema più semplice di quello di partenza; prima o poi si arriverà dunque ad un problema di dimensione sufficientemente piccola da poter essere affrontato nel caso base; a questo punto viene restituita una risposta che, a cascata e all indietro, permette di calcolare le risposte intermedie più complesse rimaste in sospeso ; Nello schema indicato restano da dettagliare caso per caso una serie di elementi: il caso base: può essere esso stesso complesso da risolvere, possono esistere più casi base distinti, ecc. il caso induttivo comprende due fasi fondamentali da progettare di volta in volta: 1. la fase dell estrapolazione del/dei sottoproblema/i; 2. la fase dello sfruttamento della/delle soluzione/i parziale/i; in genere una di queste fasi (quale delle due dipende dal procedimento di soluzione) risulta di complessità predominante rispetto all altra.

Il calcolo del fattoriale Una esempio molto semplice di problema la cui soluzione si presta ad essere descritta in maniera induttiva è il calcolo del fattoriale n! di un intero n: n!= " i =1# 2 #L# n (0!=1) La descrizione induttiva del calcolo è: caso base: per n=0 si ha direttamente n! = 1 caso induttivo:! per n>0 si ha n! = n * (n-1)! n i=1 In questo esempio: il caso base è semplice da riconoscere e calcolare, la ricorsione riguarda un solo sottoproblema la cui estrazione è semplice (si passa dal valore n al valore n-1 ) e lo sfruttamento della soluzione parziale è operata tramite la moltiplicazione; L implementazione è dunque: int fattoriale (int n) { if (n==0) return 1; else return n * fattoriale(n-1); }

I numeri di Fibonacci Nel 1202 Fibonacci si trovò a risolvere il seguente problema (che è un astrazione/semplificazione di un problema reale): Quante coppie di conigli avrò in un recinto dopo un anno se: 1. all inizio dell anno introduco una sola coppia di conigli appena nati; 2. una coppia di conigli diventa sessualmente matura dopo esattamente un mese dalla nascita; 3. esattamente ogni mese una coppia di conigli sessualmente maturi produce una nuova coppia di conigli (un maschio e una femmina); 4. i conigli non muoiono mai. La soluzione generale a questo problema è una sequenza di numeri {fib(i)} nota come sequenza di fibonacci; il valore fib(i) rappresenta il numero di coppie di conigli presenti nel recinto all inizio del mese i-esimo.

I numeri di Fibonacci L inizio della sequenza, come rappresentato in figura: numero di coppie: fib(i) è il seguente: 1, 1, 2, 3, 5, 8, 12,

I numeri di Fibonacci Un pezzo più lungo del prefisso della sequenza di Fibonacci i coppie di conigli fib(i) è il seguente: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,

Quale è la regola generale? Risposta: I numeri di Fibonacci fib(i) all inizio del mese i ci sono tutti i conigli che c erano all inizio del mese i-1 (i conigli non muoiono) e in più ci sono i nuovi nati; i nuovi nati sono nati dopo una gestazione di un mese che ogni coppia di genitori ha avviato alla maturità sessuale (cioè ad un mese di età); pertanto le nuove coppie all inizio del mese i sono tante quanti erano i conigli sessualmente maturi al mese i-1 e cioè tanti quanti erano i conigli al mese i-2; in definitiva, di conigli al mese i ce ne sono la somma di quanti c erano al mese i-1 con quanti ce n erano al mese i-2.

Quale è la regola generale? ad esempio: I numeri di Fibonacci fib(i) all inizio del mese 2 rimane la coppia introdotta all inizio, ma c è una prima coppia figlia, quindi fib(3)=1+1=2; all inizio del mese 3 restano le 2 coppie già presenti al mese 2, ed in più la coppia che già era presente al mese 1 produce una nuova coppia, per cui fib(3)=2+1=3; all inizio del mese 4 restano le 3 coppie già presenti all inizio del mese 3, ed in più le coppie fertili del mese 3 - che sono 2 perché 2 coppie erano presenti all inizio del mese 2, producono una nuova coppia ciascuna; quindi fib(4)=3+2=5; e così via

I numeri di Fibonacci La formula per calcolare i numeri di Fibonacci è dunque: fib( n) = # 1 se n = 0 oppure n =1 $ % fib(n "1) + fib(n " 2) se n >1 In questo esempio: il caso base è semplice da riconoscere e calcolare, la ricorsione riguarda due sottoproblemi di semplice individuazione (si passa dal valore n ai valori n-1! e n-2 ); lo sfruttamento della soluzione parziale è operato tramite la semplice addizione delle soluzioni dei sottoproblemi individuati; L implementazione è dunque (tre versioni equivalenti): int fib(int n) { } if (n==0 n==1) return 1; else return fib(n-1)+fib(n-2); int fib(int n) { } int fib (int n) { int ris; if (n==0 n==1) ris = 1; else ris = fib(n-1)+fib(n-2); return ris; } return (n==0 n==1)? 1 : (fib(n-1)+fib(n-2));

Si hanno tre pioli (A,B e C) Le torri di Hanoi A B C

Le torri di Hanoi Si hanno tre pioli (A,B e C) e un certo numero di dischi forati - tutti di dimensioni diverse - inizialmente disposti sul piolo A dal più grande (in fondo) al più piccolo (in cima). A B C

Le torri di Hanoi L obiettivo del gioco è mettere tutti i dischi sul piolo C, sempre in ordine dal più grande (in basso) al più piccolo (in cima), seguendo tre regole A B C

Le torri di Hanoi (1) si può spostare un solo disco alla volta; (2) si può spostare solo un disco che non ha altri dischi sopra; (3) non si può mai mettere un disco più grande su uno più piccolo. A B C

Le torri di Hanoi Soluzione del problema con 4 dischi:

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 1

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 2

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 3

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 4

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 5

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 6

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 7

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 8

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 9

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 10

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 11

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 12

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 13

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 14

Le torri di Hanoi Soluzione del problema con 4 dischi: mossa 15

Le torri di Hanoi Soluzione del problema con 4 dischi:

Le torri di Hanoi Per risolvere il problema di Hanoi con soli 4 dischi occorrono dunque 15 mosse; più in generale, la soluzione più breve per risolvere il problema con n dischi è composta da 2 n -1 mosse;

Un algoritmo per le torri di Hanoi Come si descrive induttivamente la soluzione del problema con n dischi? Caso base: se ho un solo disco da spostare da A a C, lo so spostare: A B C

Un algoritmo per le torri di Hanoi Come si descrive induttivamente la soluzione del problema con n dischi? Caso base: se ho un solo disco da spostare da A a C, lo so spostare: A B C

Un algoritmo per le torri di Hanoi Come si descrive induttivamente la soluzione del problema con n dischi? Caso base: se ho un solo disco da spostare da A a C, lo so spostare; Caso induttivo (suppongo di saper risolvere problemi con n-1 dischi): 1. metto gli n-1 dischi più piccoli da A in B A B C

Un algoritmo per le torri di Hanoi Come si descrive induttivamente la soluzione del problema con n dischi? Caso base: se ho un solo disco da spostare da A a C, lo so spostare: Caso induttivo (suppongo di saper risolvere problemi con n-1 dischi): 1. metto gli n-1 dischi più piccoli da A in B 2. metto un disco da A in C A B C

Un algoritmo per le torri di Hanoi Come si descrive induttivamente la soluzione del problema con n dischi? Caso base: se ho un solo disco da spostare da A a C, lo so spostare: Caso induttivo (suppongo di saper risolvere problemi con n-1 dischi): 1. metto gli n-1 dischi più piccoli da A in B 2. metto un disco da A in C 3. metto gli n-1 dischi più piccoli da B in C A B C

Un algoritmo per le torri di Hanoi Come si descrive induttivamente la soluzione del problema con n dischi? Caso base: se ho un solo disco da spostare da A a C, lo so spostare: Caso induttivo (suppongo di saper risolvere problemi con n-1 dischi): 1. metto gli n-1 dischi più piccoli da A in B 2. metto un disco da A in C 3. metto gli n-1 dischi più piccoli da B in C A B C

Un algoritmo per le torri di Hanoi Come si descrive induttivamente la soluzione del problema con n dischi? Caso base: se ho un solo disco da spostare da A a C, lo so spostare: Caso induttivo (suppongo di saper risolvere problemi con n-1 dischi): 1. metto gli n-1 dischi più piccoli da A in B 2. metto un disco da A in C 3. metto gli n-1 dischi più piccoli da B in C A B C

Un algoritmo per le torri di Hanoi Nel problema delle torri di Hanoi: 1. il caso base è semplice da riconoscere e risolvere; 2. la ricorsione riguarda due sottoproblemi la cui estrazione è semplice: si passa da un problema con n dischi a due problemi con n-1 dischi; 3. lo sfruttamento delle soluzioni parziali è operata tramite la giustapposizione delle mosse previste dalla soluzione del primo sottoproblema, seguita da una singola mossa, seguita ancora dalle mosse previste per la soluzione del secondo sottoproblema; L implementazione è dunque: void hanoi(char da_piolo, char a_piolo, char piolo_appoggio, int dischi) { if (dischi==1) { cout << "da " << da_piolo << " a " << a_piolo << endl; } else { hanoi(da_piolo,piolo_appoggio,a_piolo,dischi-1); cout << "da " << dal_piolo << " a " << al_piolo << endl; hanoi(piolo_appoggio,a_piolo,da_piolo,dischi-1); } }