Il calcolo del fattoriale

Slides:



Advertisements
Presentazioni simili
I numeri interi relativi
Advertisements

RICORSIONE: DEFINIZIONI RICORSIVE
Master Bioinformatica 2002: Grafi Problema: cammini minimi da tutti i vertici a tutti i vertici Dato un grafo pesato G =(V,E,w), trovare un cammino minimo.
CALCOLO COMBINATORIO: DISPOSIZIONI
INSIEMI NUMERICI I numeri
Funzioni e procedure Ogni linguaggio di programmazione ad alto livello mette a disposizione del programmatore questi strumenti, ed il C non è da meno!
Daniela Valenti, Treccani Scuola
Process synchronization
Linguaggio C++ Selezione.
Procedure e funzioni ricorsive
Lez. 11 (11/12) - PBElementi di Programmazione1 Lezione 11 Esercizi.
MATLAB.
MATLAB. Scopo della lezione Programmare in Matlab Funzioni Cicli Operatori relazionali Esercizi vari.
Dipartimento di Matematica
1 Informatica Generale Susanna Pelagatti Ricevimento: Mercoledì ore presso Dipartimento di Informatica, Via Buonarroti,
Lez. 41 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Programmazione.
esponente del radicando
Introduzione agli algoritmi. Definizione Sistema di regole e procedure di calcolo ben definite che portano alla soluzione di un problema con un numero.
Iterazione enumerativa (for)
Esercizi di esonero (a.a. 2007/2008) Compito C, terzo esercizio Data una sequenza di caratteri s1 ed una stringa s2 diciamo che s1 è contenuta in s2 se.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Costrutti iterativi Marco D. Santambrogio – Ver. aggiornata al 9 Agosto 2013.
Corso di Informatica (Programmazione)
Esercizio 4 Data una stringa P di lunghezza m e definita sullalfabeto, scrivere un programma PERL per calcolare la seguente funzione: PREFIX_FUNCTION:
MATLAB. …oggi… Programmare in Matlab Programmare in Matlab m-file m-file script script Funzioni Funzioni Cicli Cicli Operatori relazionali Operatori relazionali.
MATLAB.
MATLAB. …oggi… Programmare in Matlab Programmare in Matlab Funzioni Funzioni Cicli Cicli Operatori relazionali Operatori relazionali Indipendenza lineare,
MATLAB. …oggi… Programmare in Matlab Programmare in Matlab Funzioni Funzioni Cicli Cicli Operatori relazionali Operatori relazionali Esercizi vari Esercizi.
Primo esercizio Scrivere un programma che legge da input
Potenze di numeri relativi
DISEQUAZIONI Chiedersi quando un trinomio dato è positivo significa ricercare per quali valori di x la variabile y è positiva; in altre parole si devono.
CORSO DI PROGRAMMAZIONE II
CORSO DI PROGRAMMAZIONE II
Ordinamento di una lista: bubble-sort
I numeri relativi by iprof.
Un gioco di magia!?.
Strutture di controllo in C -- Flow Chart --
Esercizi 4 Calcolo Combinatorio.
Esercizi 4 Soluzioni Calcolo combinatorio.
"turismo archeologico e la città contemporanea" Cominciamo.
I numeri interi relativi
CONVERSIONE NUMERI INTERI CON COMPLEMENTO A DUE. I computer di oggi effettuano ogni tipo di operazione numerica, ma le prime ALU degli anni 50 erano in.
CALCOLO COMBINATORIO Prof Sandro Pistori.
Prof. Vincenzo Calamia Liceo Classico Alcamo
PROGRAMMAZIONE: linguaggi
I NUMERI INTERI Il secondo insieme che prenderemo in esame è quello dei numeri interi. Esso si indica con la lettera Z (dal tedesco Zahl = numero) e i.
In molti casi è utile assegnare a degli identificatori dei valori che restino costanti durante tutto il programma e che non possano essere cambiati nemmeno.
Massimo Comun Divisore
Lordinamento di tre numeri interi. acquisisci a,b,c (a > b) AND (a > c)(b > a) AND (b > c) (c > a) AND (c > b) Scrivi c,b,aScrivi b,c,aScrivi c,a,bScrivi.
Programmazione di Calcolatori
3 aprile 2002 Avvisi: 1 o Esonero: mercoledi 17 aprile ore 11:30 – 14:00 consulta la pag. WEB alla voce esoneri si raccomanda la puntualita!
LE PROGRESSIONI.
Giocare con la probabilità
Tail recursion: esempio
Esercizi La distanza di hamming tra due interi x e y si definisce come il numero di posizioni nella rappresentazione binaria di x e y aventi bit differenti.
Ripetizione La vera potenza dei programmi per computer risiede nella capacità di ripetere lo stesso calcolo o sequenza di istruzioni più volte, ogni volta.
Informatica B Allievi Elettrici - AA Fondamenti della programmazione in linguaggio C (II) Istruzioni e strutture di controllo.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Lab 7 – Info B Marco D. Santambrogio – Riccardo Cattaneo –
Struttura della presentazione 1 Descrizione della comunita’ di pratiche(dati da etnografia di sfondo) * quale è la comunità di pratiche? * chi sono i partecipanti?
Rappresentazione degli interi
Informatica 4 La ricorsione. Definizione di ricorsione Ricorsione è la proprietà di quei programmi che, all’interno delle istruzioni che li compongono,
Liceo Ariosto-Spallanzani
Rappresentazione dei numeri
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Lab 2 – Info B Marco D. Santambrogio – Matteo Ferroni –
Soluzione e discussione equazione 2°grado con foglio elettronico di polaris office su padlet Asus Eee Le formule da inserire si possono trovare nelle tabelle.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Lab 2 – Info B Marco D. Santambrogio – Matteo Ferroni –
Funzione potenza e funzione radice
I numeri relativi DEFINIZIONE. Si dicono numeri relativi tutti i numeri interi, razionali e irrazionali dotati di segno (positivo o negativo). ESEMPI Numeri.
I RADICALI ARITMETICI.
ESERCIZI MATLAB/OCTAVE MANOLO VENTURIN UNIVERSITÀ DEGLI STUDI DI PADOVA DIP. DI MATEMATICA PURA ED APPLICATA A. A. 2007/2008.
Transcript della presentazione:

Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita dove n è un numero intero non negativo DEI - Univ. Padova (Italia)

Il calcolo del fattoriale Vediamo di capire cosa significa… 5! = 5(5-1)! = 5·4! = 5·4·3·2·1 = 120 4! = 4(4-1)! = 4·3! = 4·3·2·1 = 24 3! = 3(3-1)! = 3·2! = 3·2·1 = 6 2! = 2(2-1)! = 2·1! = 2·1 = 2 1! = 1(1-1)! = 1·0! = 1·1 = 1 0! = 1 Quindi, per ogni n intero positivo, il fattoriale di n è il prodotto dei primi n numeri interi positivi DEI - Univ. Padova (Italia)

Il calcolo del fattoriale Scriviamo una funzione per calcolare il fattoriale function res=Fattoriale(n); if(n<0) res=-1; return; end; res=1; for ct=1:n res=res*ct; DEI - Univ. Padova (Italia)

Il calcolo del fattoriale Realizzando direttamente la definizione, sarebbe stato più naturale scrivere: function res=Fattoriale(n); if(n<0) res=-1; return; end; if (n==0) res=1; else res=n*Fattoriale(n-1); DEI - Univ. Padova (Italia)

ricorsione metodo ricorsivo 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 molti errori di difficile diagnosi DEI - Univ. Padova (Italia)

La ricorsione: come funziona? Quando una funzione viene invocata: si sospende l’esecuzione del metodo invocante (le variabili locali rimangono congelate) si esegue il metodo invocato fino alla sua terminazione (con nuove variabili locali) si riprende l’esecuzione del metodo invocante dal punto in cui era stata sospesa (recuperando le variabili locali) La stessa sequenza di azioni viene compiuta quando un metodo invoca sé stesso. DEI - Univ. Padova (Italia)

La ricorsione Vediamo la sequenza usata per calcolare 3! si invoca Fattoriale(3) Fattoriale(3) invoca Fattoriale (2) Fattoriale(2) invoca Fattoriale (1) Fattoriale(1) invoca Fattoriale (0) Fattoriale(0) restituisce 1 Fattoriale(1) restituisce 1 Fattoriale(2) restituisce 2 Fattoriale(3) restituisce 6 Si crea quindi una lista LIFO (uno stack) di metodi “in attesa”, ciascuno con le sue variabili locali, che si allunga e che poi si accorcia fino ad estinguersi DEI - Univ. Padova (Italia)

La ricorsione In ogni caso, anche se il meccanismo di funzionamento della ricorsione può sembrare complesso, la chiave per un suo utilizzo proficuo è dimenticarsi come funziona la ricorsione, ma sapere come vanno scritti i metodi ricorsivi perché il tutto funzioni! Esistono infatti due regole ben definite che vanno utilizzate per scrivere metodi ricorsivi che funzionino DEI - Univ. Padova (Italia)

Caso base Prima regola 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 Nell’esempio del fattoriale, il caso base era a volte ci sono più casi base, non è necessario che il caso base sia unico if (n == 0) res = 1; DEI - Univ. Padova (Italia)

Passo ricorsivo Seconda regola 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 il concetto di “problema più semplice” varia di volta in volta: in generale, bisogna avvicinarsi ad un caso base else res = n*Fattoriale(n-1); DEI - Univ. Padova (Italia)

Ricorsione e algoritmi Le regole appena viste sono fondamentali per poter dimostrare che la soluzione ricorsiva di un problema sia un algoritmo in particolare, che arrivi a conclusione in un numero finito di passi Le chiamate ricorsive potrebbero succedersi una dopo l’altra, all’infinito DEI - Univ. Padova (Italia)

Ricorsione e algoritmi Se ad ogni invocazione il problema diventa sempre più semplice e si avvicina al caso base la soluzione del caso base non richiede ricorsione allora certamente la soluzione viene calcolata in un numero finito di passi, per quanto complesso possa essere il problema DEI - Univ. Padova (Italia)

Ricorsione infinita Abbiamo visto 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 DEI - Univ. Padova (Italia)

Ricorsione Infinita Il seguente programma presenta ricorsione infinita: Il programma terminerà con la segnalazione dell’errore StackOverflowError il runtime stack è la struttura dati che gestisce le invocazioni in attesa overflow significa trabocco function res=InifinteRecursion(n) disp ([‘Chiamata ’ ,n ,’\n’]; res= InifinteRecursion(n+1); return; DEI - Univ. Padova (Italia)

Ricorsione in coda Esistono diversi tipi di ricorsione Il modo visto fino ad ora si chiama ricorsione in coda (tail recursion) il metodo ricorsivo esegue una sola invocazione ricorsiva e tale invocazione è l’ultima azione del metodo function res = RicorroInCoda(. . .) . . . res=RicorroInCoda(. . .); return; DEI - Univ. Padova (Italia)

Iterazione e ricorsione La ricorsione in coda può sempre essere agevolmente eliminata, trasformando il metodo ricorsivo in un metodo che usa un ciclo function res=Fattoriale(n) if (n == 0) res = 1; else res=n*Fattoriale(n-1); return; function res=Fattoriale(n) res=1; for i=1:n res=res*i; end return; DEI - Univ. Padova (Italia)

Ricorsione: motivazioni Allora, a cosa serve la ricorsione in coda? Non è necessaria, però in alcuni casi rende il codice più leggibile È utile quando la soluzione del problema è esplicitamente ricorsiva (es. fattoriale) In ogni caso, la ricorsione in coda è meno efficiente del ciclo equivalente, perché il sistema deve gestire le invocazioni sospese DEI - Univ. Padova (Italia)

Ricorsione multipla Si parla di ricorsione multipla quando un metodo invoca se stesso più volte durante una sua esecuzione la ricorsione multipla è ancora più difficile da eliminare, ma è sempre possibile Esempio: il calcolo dei numeri di Fibonacci DEI - Univ. Padova (Italia)

Numeri di Fibonacci Il metodo Fib realizza una ricorsione multipla function res = Fib(n) if(n<0) res=-1; return; end; if (n < 2) res= n; else res=Fib(n-1) + Fib(n-2); DEI - Univ. Padova (Italia)

Ricorsione multipla La ricorsione multipla va usata con molta attenzione, perché può portare a programmi molto inefficienti Eseguendo il calcolo dei numeri di Fibonacci di ordine crescente... … si nota che il tempo di elaborazione cresce MOLTO rapidamente… quasi 3 milioni di invocazioni per calcolare Fib(31) !!!! DEI - Univ. Padova (Italia)

Torre di Hanoi Il rompicapo è costituito da tre pile di dischi (“torri”) allineate all’inizio tutti i dischi si trovano sulla pila di sinistra alla fine tutti i dischi si devono trovare sulla pila di destra I dischi sono tutti di dimensioni diverse e quando si trovano su una pila devono rispettare la seguente regola nessun disco può avere sopra di sé dischi più grandi DEI - Univ. Padova (Italia)

Torre di Hanoi Situazione iniziale Situazione finale DEI - Univ. Padova (Italia)

Torre di Hanoi Situazione iniziale Situazione finale DEI - Univ. Padova (Italia)

Torre di Hanoi Per risolvere il rompicapo bisogna: spostare un disco alla volta un disco può essere rimosso dalla cima della torre ed inserito in cima ad un’altra torre nessun disco può avere sopra di sé dischi più grandi DEI - Univ. Padova (Italia)

Torre di Hanoi Per il rompicapo delle Torri di Hanoi è noto un algoritmo di soluzione ricorsivo: Il problema generale consiste nello spostare n dischi da una torre ad un’altra, usando la terza torre come deposito temporaneo Per spostare n dischi da una torre all’altra si suppone, come sempre si fa nella ricorsione, di saper spostare n-1 dischi da una torre all’altra DEI - Univ. Padova (Italia)

Torre di Hanoi Il caso base si ha quando n vale 1, in questo caso possiamo spostare liberamente il disco da una torre ad un’altra Per spostare n dischi dalla torre 1 alla torre 3 gli n-1 dischi in cima alla torre 1 vengono spostati sulla torre 2, usando la torre 3 come deposito temporaneo (si usa una chiamata ricorsiva, al termine della quale la torre 3 rimane vuota) il disco rimasto nella torre 1 viene portato nella torre 3 gli n-1 dischi in cima alla torre 2 vengono spostati sulla torre 3, usando la torre 1 come deposito temporaneo (si usa una chiamata ricorsiva, al termine della quale la torre 1 rimane vuota) DEI - Univ. Padova (Italia)

Torre di Hanoi DEI - Univ. Padova (Italia)

Torre di Hanoi Algoritmo Hanoi(n, da, a, int) input: il numero di dichi n, il perno di partenza, di arrivo e intermedio output: le mosse necessarie if n = 1 then muovi (1, da, a) else hanoi (n-1, da, int, a) muovi (n, da, a) hanoi (n-1, int, a, da) DEI - Univ. Padova (Italia)

Torre di Hanoi Si può dimostrare che il numero di mosse necessarie per risolvere il rompicapo con l’algoritmo proposto è pari a: 2n – 1 Il tempo necessario alla soluzione è proporzionale al numero di mosse (ogni mossa richiede un tempo costante) DEI - Univ. Padova (Italia)

Torre di Hanoi: soluzione function Sposta(n, da, a, buffer) if(n==1) disp ([‘Sposto il disco da ’, da, ‘a ‘,a,’\n’]; else Sposta(n-1, da, buffer, a); Sposta(n, buffer, a, da); end; return; DEI - Univ. Padova (Italia)

Torre di Hanoi Una leggenda narra che alcuni monaci buddisti in un tempio dell’Estremo Oriente siano da sempre impegnati nella soluzione del rompicapo, spostando fisicamente i loro 64 dischi da una torre all’altra, consapevoli che quando avranno terminato il mondo finirà Sono necessarie 264 mosse, che sono circa 16 miliardi di miliardi di mosse Supponendo che i monaci facciamo una mossa ogni minuto, essi fanno circa 500000 mosse all’anno, quindi il mondo finirà tra circa 30 mila miliardi di anni Un processore ad 1GHz che fa una mossa ad ogni intervallo di clock (un miliardo di mosse al secondo…) impiega 16 miliardi di secondi, che sono circa 500 anni... DEI - Univ. Padova (Italia)

Ordinamento efficiente: quick-sort Si cerca di ridurre la parte disordinata di più di un elemento per volta (a differenza di selection-sort e bubble-sort) L’idea è di ordinare parzialmente l’array, in modo che una parte contenga tutti i valori minori di un valore dato (pivot), e l’altra parte contenga tutti elementi maggiori Si applica poi l’algoritmo ricorsivamente alle due parti DEI - Univ. Padova (Italia)

Ordinamento: quick-sort Passo 1: Scelgo un valore nell’array da usare come pivot. Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 87 14 27 22 elemento pivot Linea di demarcazione delle due parti parzialmente ordinate Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 87 22 27 DEI - Univ. Padova (Italia)

Ordinamento: quick-sort Passo 2: Applico di nuovo il procedimento alle due parti separatamente Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 87 22 27 Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 87 22 27 elemento pivot elemento pivot Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 22 87 27 DEI - Univ. Padova (Italia)

Ordinamento: quick-sort Passo 3: Applico di nuovo il procedimento alle due parti separatamente Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 87 22 27 Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 22 87 27 Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 22 87 27 DEI - Univ. Padova (Italia)

Ordinamento: quick-sort Passo 4: Applico di nuovo il procedimento alle varie parti separatamente Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 87 22 27 Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 22 87 27 Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 22 87 27 Prova(4) Prova(5) 27 87 DEI - Univ. Padova (Italia)

Quicksort in Matlab function y=quicksort(x,pstart,pend); x: vettore da ordinare pstart: indice del primo elemento a cui applicare quicksort pend; indice dell’ultimo elemento a cui applicare quicksort Controlla se siamo nel caso base: la lunghezza (indice dell’ultimo elemento meno indice del primo elemento) della parte di vettore da ordinare è 1 function y=quicksort(x,pstart,pend); if((pend-pstart)<=1) y=x; return; end; [y,pivot]=partiziona(x,pstart,pend); y=quicksort(y,pstart,pivot); y=quicksort(y,pivot+1,pend); Chiamata alla funzione che ordina parzialmente la parte di vettore che va dall’indice pstart all’indice pend Chiamate ricorsive della funzione quicksort sulle due parti di vettore parzialmente ordinate DEI - Univ. Padova (Italia)

Funzione di partizionamento La funzione centrale di quicksort è la funzione che crea due sotto-vettori parzialmente ordinati utilizzando un elemento di pivot Come elemento di pivot scegliamo di utilizzare quello che sta approssimativamente al centro del vettore (ma si possono utilizzare altre strategie di scelta) DEI - Univ. Padova (Italia)

Ordinamento: partizionamento Passo 1: Scelgo un valore nell’array da usare come pivot. Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 87 14 27 22 elemento pivot indice i che scorre dalla fine verso l’inizio indice j che scorre dalla fine verso l’inizio DEI - Univ. Padova (Italia)

Ordinamento: partizionamento Passo 2: Faccio scorrere indietro j fino a che gli elementi alla posizione j-esima sono maggiori o uguali al valore del pivot. Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 87 14 27 22 elemento pivot indice i che scorre dalla fine verso l’inizio indice j che scorre dalla fine verso l’inizio DEI - Univ. Padova (Italia)

Ordinamento: partizionamento Passo 3: Faccio scorrere avanti i fino a che gli elementi alla posizione i-esima sono minori o uguali al valore del pivot, ed i è minore di j Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 87 14 27 22 elemento pivot indice i che scorre dalla fine verso l’inizio indice j che scorre dalla fine verso l’inizio DEI - Univ. Padova (Italia)

Ordinamento: partizionamento Passo 4: Scambio il valore che si trova alla i-esima posizione con quello della j-esima, poi faccio scorrere i e j nelle rispettive direzioni. Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 87 27 22 elemento pivot indice j che scorre dalla fine verso l’inizio indice i che scorre dalla fine verso l’inizio DEI - Univ. Padova (Italia)

Ordinamento: partizionamento Passo 5: Se i è minore di j riprendo dal passo 2, altrimenti restituisco j come elemento di separazione fra i due sotto-vettori parzialmente ordinati Prova(1) Prova(2) Prova(3) Prova(4) Prova(5) 1 14 87 27 22 elemento pivot indice j che scorre dalla fine verso l’inizio indice i che scorre dalla fine verso l’inizio DEI - Univ. Padova (Italia)

Partizionamento in Matlab x: vettore da ordinare pstart: indice del primo elemento a cui applicare quicksort pend; indice dell’ultimo elemento a cui applicare quicksort function [y,pivot]=partiziona(x,pstart,pend); y=x; pivot=round(0.5*(pstart+pend)); p=x(pivot); i=pstart; j=pend; while(i<j) while(j>=1 & x(j)>p) j=j-1; end; while(x(i)<p & i<j) i=i+1; tmp=y(i); y(i)=y(j); y(j)=tmp; pivot=j+1; Inizializzazione. Scelgo come pivot l’elemento centrale Scorre j indietro ed i in avanti finchè non si incrociano Fa scorrere indietro l’indice j Fa scorrere indietro l’indice i Scambia gli elementi che sono dalla parte sbagliata dell’array rispetto al pivot DEI - Univ. Padova (Italia)

Quick-sort: efficienza Nel caso medio ad ogni chiamata ricorsiva si divide l’array in due parti da ordinare di lunghezza approssimativamente uguale al numero di elementi diviso per due n Chiamata 1 n/2 n/2 Chiamata 2 n/4 n/4 n/4 n/4 Chiamata 3 DEI - Univ. Padova (Italia)

Quick-sort: efficienza Per n elementi si ha che dividendo in maniera binaria e bilanciata si devono effettuare log(n) chiamate ricorsive Ad ogni chiamata ricorsiva si esaminano tutti gli elementi dell’array da ordinare DEI - Univ. Padova (Italia)