Programmazione Funzionale Esercizi sulle liste Davide Mottin - Themis Palpanas April 16, 2014 1/15 Ripasso Costruire una funzione ricorsiva Liste Enumerazione di insiemi Liste strettamente crescenti La funzione map La funzione filter Insieme delle parti Sottoinsiemi di determinata cardinalit`a Sommario 2/15 Suggerimenti per “pensare” ricorsivo 1. Leggere attentamente il problema da risolvere 2. Pensare al caso pi` u banale nel quale la funzione da costruire sia definita e per il quale possiamo dare il risultato immediatamente (Suggerimento: in molte occasioni il caso base `e il minimo di un insieme, se ordinato, per esempio lo 0 per i numeri naturali, [] per le liste, ”” per le stringhe) 3. Pensare a quale valore la funzione assume nel caso ci si trovi di fronte all’input (caso) base, senza preoccuparci delle chiamate ricorsive 4. Pensare al caso ricorsivo in questo modo: 4.1 supporre di sapere risolvere il problema nel caso immediatamente pi` u semplice 4.2 avendo gi`a il risultato del caso semplice costruire il caso pi` u complesso manipolando il risultato della chiamata ricorsiva opportunamente In un certo senso si pensa tutto in maniera bottom-up ossia dal basso verso l’alto. Ripasso 3/15 Suggerimenti per “pensare” ricorsivo Prendiamo per esempio la funzione che conta il numero di elementi in una lista l e t rec l e n g t h = f u n c t i o n [] − > 0 | x : : x s −> 1 + l e n g t h x s ; ; I I Ripasso caso base: la lista pi` u piccola pensabile `e la lista vuota, quindi se troviamo [] allora sappiamo PER DEFINIZIONE che la lunghezza di una lista vuota `e 0 (nota che non abbiamo avuto bisogno di nessun altra operazione, lo sappiamo senza doverlo calcolare) caso ricorsivo: allora vediamo di estrarre un elemento dalla lista e supponiamo di SAPERE che la funzione length xs restituisce la lunghezza della lista xs, perch´e un oracolo ci ha detto che lo sappiamo calcolare. Cosa dobbiamo fare per ottenere la lunghezza della lista x::xs dato in input la lunghezza di xs? Banalmente dobbiamo aggiungere 1 perch´e abbiamo trovato un elemento in pi` u. 4/15 Enumerazione di insiemi Costrure una funzione enumerate:’a list -> (’a * int) list che preso in input una lista costruisca la lista di coppie formate da un elemento della lista in input e da un numero progressivo che rappresenta l’indice di quell’elemento nella lista. Esempio enumerate [’a’;’b’;’c’];; - : (char * int) list = [(’a’, 0); (’b’, 1); (’c’, 2)] Liste 5/15 Enumerazione di insiemi - Soluzione l e t enumerate l = l e t r e c aux c = f u n c t i o n [ ] −> [ ] | x : : x s −> ( x , c ) : : aux ( c +1) x s i n aux 0 l ; ; Liste 6/15 Liste strettamente crescenti Costruire una funzione increasing : ’a list -> ’a list che preso in input una lista di elementi restituisca la lista che rimuove elementi se non sono in ordine crescente Esempio increasing [2;5;3;8;1;2;3];; - : int list = [2; 5; 8] Liste 7/15 Liste strettamente crescenti Costruire una funzione increasing : ’a list -> ’a list che preso in input una lista di elementi restituisca la lista che rimuove elementi se non sono in ordine crescente Esempio increasing [2;5;3;8;1;2;3];; - : int list = [2; 5; 8] Suggerimento 1. Si pu` o pensare di tenere traccia del massimo elemento letto fino a quel punto in una funzione interna. Liste 7/15 Liste strettamente crescenti - Soluzione let increasing = function [ ] −> [ ] | x : : x s −> l e t r e c aux max = f u n c t i o n [ ] −> [ ] | x : : x s −> i f x > max t h e n x : : ( aux x x s ) else aux max x s i n x : : ( aux x x s ) ; ; Liste 8/15 La funzione map La funzione map `e una funzione di ordine superiore che presa in input una lista e una funzione generica applica la funzione ad ogni elemento della lista. La sua firma `e map: (’a -> ’b) -> ’a list -> ’b list l e t r e c map f = f u n c t i o n [ ] −> [ ] | x : : x s −> ( f x ) : : map f x s ; ; Liste 9/15 La funzione filter Costruire una funzione che “filtri” una lista usando la funzione booleana f in ingresso, ossia che se f `e vera aggiunge l’elemento alla lista altrimenti no Liste 10/15 La funzione filter Costruire una funzione che “filtri” una lista usando la funzione booleana f in ingresso, ossia che se f `e vera aggiunge l’elemento alla lista altrimenti no Suggerimento 1. La funzione filter non `e molto diversa da map, solo che se f applicata ad un argomento `e verificata si concatener`a l’elemento alla lista, altrimenti si richiamer`a la funzione filter sulla sottolista. Liste 10/15 La funzione filter - Soluzione l e t rec f i l t e r f = f u n c t i o n [ ] −> [ ] | x : : x s −> i f ( f x ) then x : : ( f i l t e r f xs ) e l s e ( f i l t e r f xs ) ; ; Liste 11/15 La funzione filter - Soluzione l e t rec f i l t e r f = f u n c t i o n [ ] −> [ ] | x : : x s −> i f ( f x ) then x : : ( f i l t e r f xs ) e l s e ( f i l t e r f xs ) ; ; E se volessimo costruire una funzione che preso in input una lista di interi restituisca la lista con i soli numeri pari? Liste 11/15 La funzione filter - Soluzione l e t rec f i l t e r f = f u n c t i o n [ ] −> [ ] | x : : x s −> i f ( f x ) then x : : ( f i l t e r f xs ) e l s e ( f i l t e r f xs ) ; ; E se volessimo costruire una funzione che preso in input una lista di interi restituisca la lista con i soli numeri pari? Soluzione. let only even lst = filter (fun x -> x mod 2 = 0) lst;; Liste 11/15 Insieme delle parti Costruire una funzione che calcoli l’insieme delle parti, ossia che dato in input una lista restitusca la lista di tutte le possibili sottoliste. e.g. powerset [1;2] = [[]; [1]; [2]; [1;2]] Liste 12/15 Insieme delle parti Costruire una funzione che calcoli l’insieme delle parti, ossia che dato in input una lista restitusca la lista di tutte le possibili sottoliste. e.g. powerset [1;2] = [[]; [1]; [2]; [1;2]] Hint 1. L’insieme delle parti ha una definizione ricorsiva in quanto lo si pu`o pensare come caso base restituisca una lista di liste vuote (i.e. [[]]) e nel caso ricorsivo come la concatenazione (operatore @) dell’insieme delle parti ottenuto rimuovendo un elemento e la lista di sottoinsiemi ottenuti aggiungendo l’elemento rimosso ad essi Liste 12/15 Insieme delle parti Costruire una funzione che calcoli l’insieme delle parti, ossia che dato in input una lista restitusca la lista di tutte le possibili sottoliste. e.g. powerset [1;2] = [[]; [1]; [2]; [1;2]] Hint 1. L’insieme delle parti ha una definizione ricorsiva in quanto lo si pu`o pensare come caso base restituisca una lista di liste vuote (i.e. [[]]) e nel caso ricorsivo come la concatenazione (operatore @) dell’insieme delle parti ottenuto rimuovendo un elemento e la lista di sottoinsiemi ottenuti aggiungendo l’elemento rimosso ad essi Hint 2. Si pu`o usare la funzione map per aggiungere ad ogni sottolista un elemento, usando la funzione fun l -> x::l Liste 12/15 Insieme delle parti - Soluzione l e t rec powerset = f u n c t i o n [ ] −> [ [ ] ] | x : : x s −> l e t sub = p o w e r s e t x s i n sub @ ( map ( f u n l −> x : : l ) sub ) ; ; Liste 13/15 Sottoinsiemi di cardinalit`a almeno n Costruire una funzione che rimuova le liste di cardinalit`a < n dalla dalla liste di tutte le sottoliste Liste 14/15 Sottoinsiemi di cardinalit`a almeno n Costruire una funzione che rimuova le liste di cardinalit`a < n dalla dalla liste di tutte le sottoliste Hint 1.Usare le funzioni filter e length Liste 14/15 Sottoinsiemi di cardinalit`a almeno n - Soluzione l e t r e c remove n l s t = f i l t e r ( f u n l −> ( l e n g t h l ) > n ) ( p o w e r s e t l s t ) ; ; Liste 15/15
© Copyright 2024 ExpyDoc