├── Esami ├── text.txt ├── text2.txt ├── test.txt ├── 2019_07.sml ├── 2020_02.sml ├── 2019_06.sml ├── 2018_06.sml ├── 2021_02.sml ├── 2018_08.sml ├── 2022_07.sml ├── 2019_09.sml ├── 2023_06.sml ├── 2020_01.sml ├── 2016_06_T2.sml ├── 2021_07.sml ├── 2016_06_T1.sml ├── 2017_06_T1.sml ├── 2024_01.sml ├── 2017_02.sml ├── 2016_08.sml ├── 2015_08.sml ├── 2017_06_T2.sml ├── 2015_06.sml ├── 2017_07_T1.sml ├── 2017_07_T2.sml ├── 2018_07.sml ├── 2020_09.sml ├── 2020_06_T2.sml ├── 2020_06_T1.sml ├── 2022_01.sml ├── 2024_02.sml ├── 2017_09.sml ├── 2018_01.sml ├── 2021_06.sml ├── 2022_06.sml ├── 2016_07_T1.sml ├── 2023_07.sml ├── 2015_07.sml ├── 2020_07.sml ├── 2023_02.sml ├── 2024_06.sml ├── 2015_09.sml ├── 2016_07_T2.sml └── Esami.md ├── Esercizi ├── test.txt ├── esercizio09.sml ├── esercizio14.sml ├── esercizio03.sml ├── esercizio01.sml ├── esercizio08.sml ├── esercizio16.sml ├── esercizio06.sml ├── esercizio21.sml ├── esercizio15.sml ├── esercizio10.sml ├── esercizio22.sml ├── esercizio20.sml ├── esercizio19.sml ├── esercizio07.sml ├── esercizio12.sml ├── esercizio05.sml ├── esercizio02.sml ├── esercizio04.sml ├── esercizio18.sml ├── esercizio17.sml ├── esercizio23.sml ├── esercizio11.sml ├── esercizio13.sml └── esercizio24.sml ├── Esami.pdf ├── ML for Dummies.pdf ├── Slide corso ├── Lab01.pdf ├── Lab02.pdf ├── Lab03.pdf ├── Lab04.pdf ├── Lab05.pdf ├── Lab06.pdf ├── Lab07.pdf ├── Lab08.pdf ├── Lab09.pdf └── Lab10.pdf └── README.md /Esami/text.txt: -------------------------------------------------------------------------------- 1 | ab e ad c -------------------------------------------------------------------------------- /Esami/text2.txt: -------------------------------------------------------------------------------- 1 | abcdef -------------------------------------------------------------------------------- /Esami/test.txt: -------------------------------------------------------------------------------- 1 | bbacbbefbb54 -------------------------------------------------------------------------------- /Esercizi/test.txt: -------------------------------------------------------------------------------- 1 | ciao come va oggi? Io bene spero anche voi -------------------------------------------------------------------------------- /Esami.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Esami.pdf -------------------------------------------------------------------------------- /ML for Dummies.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/ML for Dummies.pdf -------------------------------------------------------------------------------- /Slide corso/Lab01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab01.pdf -------------------------------------------------------------------------------- /Slide corso/Lab02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab02.pdf -------------------------------------------------------------------------------- /Slide corso/Lab03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab03.pdf -------------------------------------------------------------------------------- /Slide corso/Lab04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab04.pdf -------------------------------------------------------------------------------- /Slide corso/Lab05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab05.pdf -------------------------------------------------------------------------------- /Slide corso/Lab06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab06.pdf -------------------------------------------------------------------------------- /Slide corso/Lab07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab07.pdf -------------------------------------------------------------------------------- /Slide corso/Lab08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab08.pdf -------------------------------------------------------------------------------- /Slide corso/Lab09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab09.pdf -------------------------------------------------------------------------------- /Slide corso/Lab10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pater999/UNITN-linguaggi-programmazione-SML/HEAD/Slide corso/Lab10.pdf -------------------------------------------------------------------------------- /Esami/2019_07.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2019 3 | 4 | L'esame era molto simile a quello di giugno dovrebbe essere cambiata solo l'operazione da svolgere sugli 5 | elementi. 6 | Sfortunatamente non sono riuscito a reperire il testo :( 7 | 8 | *) -------------------------------------------------------------------------------- /Esercizi/esercizio09.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 9 3 | Testo: 4 | Scrivere una funzione "f" che concateni 2 liste 5 | 6 | SOLUZIONE: 7 | *) 8 | 9 | fun f a b = a @ b; 10 | 11 | (* ESEMPIO ESECUZIONE: *) 12 | 13 | f [1,2,3] [5]; -------------------------------------------------------------------------------- /Esercizi/esercizio14.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 14 3 | Testo: 4 | Scrivere una funzione sum che somma una lista di interi 5 | 6 | SOLUZIONE: 7 | *) 8 | 9 | val rec sum = fn [] => 0 10 | | (a::l) => a + sum l; 11 | 12 | (* ESEMPIO ESECUZIONE: *) 13 | 14 | sum [1,2]; 15 | sum [2,4,6]; -------------------------------------------------------------------------------- /Esercizi/esercizio03.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 3 3 | Testo: 4 | Scrivere una funzione "power : int * int -> int" in modo che, per m>=0 power(n,m) = n^m 5 | Assumete che 0^0 risulti 1. 6 | 7 | SOLUZIONE: 8 | *) 9 | 10 | fun power(n,m) = if m=0 then 1 else n * power(n,m-1); 11 | 12 | (* ESEMPIO ESECUZIONE: *) 13 | 14 | power (0,0); 15 | power (2,4); 16 | power (10,3); 17 | 18 | -------------------------------------------------------------------------------- /Esercizi/esercizio01.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 1 3 | Testo: 4 | Scrivere una funzione f che ritorna "uno" se riceve come paramentro 1 e "qualcos'altro" altrimenti. 5 | 6 | SOLUZIONE: 7 | *) 8 | 9 | val rec f = fn 1 => "uno" 10 | | _ => "qualcos'altro"; 11 | 12 | (* ESEMPIO ESECUZIONE: *) 13 | 14 | f 1; 15 | f 2; 16 | f 3; 17 | (* f "ciao"; da errore perchè il parametro deve essere di tipo intero *) -------------------------------------------------------------------------------- /Esercizi/esercizio08.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 8 3 | Testo: 4 | Scrivere una funzione "mul" che calcoli n ∗ z senza usare la moltiplicazione, 5 | dove n è un numero intero positivo e z è un numero intero 6 | 7 | SOLUZIONE: 8 | *) 9 | 10 | fun mul(n,z) = if(n=0) then 0 else if (n=1) then z else z+mul(n-1,z); 11 | 12 | (* ESEMPIO ESECUZIONE: *) 13 | 14 | mul(3,4); 15 | mul(0,1); 16 | mul(3,0); 17 | mul(10,10); -------------------------------------------------------------------------------- /Esercizi/esercizio16.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 16 3 | Testo: 4 | Scrivere una funzione "copy: int * ’a -> ’a list" tale che: 5 | copy(0,5) = [] 6 | copy(1,5) = [5] 7 | copy(3,"a") = ["a","a","a"] 8 | copy(3,copy(1,8)) = [[8],[8],[8]] 9 | 10 | SOLUZIONE: 11 | *) 12 | 13 | fun copy(0,x) = [] 14 | | copy(n,x) = x::copy(n-1,x); 15 | 16 | (* ESEMPIO ESECUZIONE: *) 17 | 18 | copy(0,5); 19 | copy(1,5); 20 | copy(3,"a"); 21 | copy(3,copy(1,8)); 22 | -------------------------------------------------------------------------------- /Esercizi/esercizio06.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 6 3 | Testo: 4 | Scrivere una funzione che restituisca -1 per i numeri negativi, 0 per 0 e +1 per 5 | argomenti positivi. Si può usare il pattern matching? 6 | 7 | SOLUZIONE: 8 | *) 9 | 10 | fun es(x) = if (x=0) then 0 else if (x<0) then ~1 else 1; 11 | 12 | (* Non si può usare pattern matching *) 13 | 14 | (* ESEMPIO ESECUZIONE: *) 15 | 16 | es 0; 17 | es 2340; 18 | es ~53; 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Esercizi/esercizio21.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 21 3 | Testo: 4 | Considera la seguente struttura dati “binary tree”: 5 | *) 6 | datatype 'a btree = emptybt | consbt of 'a * 'a btree * 'a btree; 7 | (* 8 | Scrivere una funzione "sum_tree : int btree -> int" la quale ritorna la somma di tutti gli elementi 9 | dell'albero 10 | 11 | SOLUZIONE: 12 | *) 13 | 14 | fun sum_tree emptybt = 0 15 | | sum_tree (consbt(x,t1,t2)) = x + sum_tree t1 + sum_tree t2; 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Esercizi/esercizio15.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 15 3 | Testo: 4 | Scrivere una funzione isPalindroma che restituisca true se una lista è palindroma false altrimenti. 5 | 6 | es. isPalindroma [1,2,3,4] 7 | false 8 | 9 | es. isPalindroma [1,2,3,2,1] 10 | true 11 | 12 | SOLUZIONE: 13 | *) 14 | 15 | val rec isPalindroma = fn l => if l = List.rev l then true else false; 16 | 17 | (* ESEMPIO ESECUZIONE: *) 18 | 19 | isPalindroma [1,2,3,2,1]; 20 | isPalindroma ["A","A","D","D","A","A"]; 21 | isPalindroma [1,2,3]; -------------------------------------------------------------------------------- /Esercizi/esercizio10.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 10 3 | Testo: 4 | Scrivere una funzione "f" che dato un numero x e una lista di interi ordinata 5 | restituisca una lista ordinata contente x. 6 | 7 | es. f 5 [1,2,3,4,6,7] 8 | [1,2,3,4,5,6,7] 9 | 10 | es. f 5 [5,5,5,5,6] 11 | [5,5,5,5,5,6] 12 | 13 | SOLUZIONE: 14 | *) 15 | 16 | fun f x [] = x::[] 17 | | f x (a::b) = if x > a then a::(f x b) else x::(a::b); 18 | 19 | (* ESEMPIO ESECUZIONE: *) 20 | 21 | f 5 [1,2,3,4,6,7]; 22 | f 5 [5,5,5,5,6]; 23 | f 1 []; 24 | f 9 [1,2]; -------------------------------------------------------------------------------- /Esercizi/esercizio22.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 22 3 | Testo: 4 | Scrivere una funzione che scambia gli elementi alternati di una lista. 5 | 6 | Esempio: 7 | Se a = [a1, . . . , an], il risultato dovrà essere a = [a2, a1, a4, , a3 . . . , an]. Se n è dispari 8 | an dovrà rimanere in fondo. 9 | 10 | SOLUZIONE: 11 | *) 12 | 13 | fun flip [] = [] 14 | | flip [x] = [x] 15 | | flip (x::y::r) = (y::x::flip(r)); 16 | 17 | (* ESEMPIO ESECUZIONE: *) 18 | 19 | flip [1,2,3,4,5,6]; 20 | flip [1,2,3]; 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Esercizi/esercizio20.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 20 3 | Testo: 4 | Scrivere una funzione "flatten" la quale prende in input una lista di liste e restituisce 5 | una lista formata da tutti gli elementi nello stesso ordine in cui appaiono. 6 | 7 | Esempio: 8 | flatten [[1,2],[2,3,4],[5],[],[6,7]] = [1,2,2,3,4,5,6,7] 9 | 10 | SOLUZIONE: 11 | *) 12 | 13 | fun flatten [] = [] 14 | | flatten (x::l) = x @ flatten l; 15 | 16 | (* ESEMPIO ESECUZIONE: *) 17 | flatten [] ; 18 | flatten [[]]; 19 | flatten [["a"],["b","a"]]; 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Esercizi/esercizio19.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 19 3 | Testo: 4 | Scrivere una funzione "first_list: (’a * ’b) list -> ’a list" la quale 5 | ritorna una lista formata dal primo elemento di ogni lista. 6 | Esempio: 7 | first_list [(1,"a"),(2,"b"),(3,"c")] = [1,2,3] 8 | 9 | SOLUZIONE: 10 | *) 11 | 12 | fun first_list [] = [] 13 | | first_list((x,y)::l) = x::first_list l; 14 | 15 | (* ESEMPIO ESECUZIONE: *) 16 | 17 | first_list [] ; 18 | first_list [(1,2),(1,3)]; 19 | first_list [(1,"a"),(2,"b"),(3,"c")]; 20 | first_list [([],"a"),([1],"b"),([1,2],"c")]; 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Esercizi/esercizio07.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 7 3 | Testo: 4 | Scrivere una funzione che restituisca il più piccolo dei suoi due argomenti 5 | (a) usando argument pattern 6 | (b) usando una dichiarazione locale 7 | 8 | SOLUZIONE: 9 | *) 10 | 11 | fun minA(a,b) = if (a b then false else isUguale l p; 14 | 15 | (* ESEMPIO ESECUZIONE: *) 16 | 17 | isUguale [] []; 18 | isUguale [1] [1]; 19 | isUguale [1,2,3,4] [1,2,3,4]; 20 | isUguale [1,2,3,4] []; 21 | isUguale [1,2,3,4] [1,2,3,5]; 22 | isUguale [1,2,3,4] [1,2,3]; -------------------------------------------------------------------------------- /Esercizi/esercizio05.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 5 3 | Testo: 4 | Scrivere una funzione che restituisca il valore 2 per gli argomenti 0, 1 e 2 5 | e restituisca 3 per tutti gli altri argomenti (interi). Scrivi due soluzioni: 6 | (a) usando pattern matching 7 | (b) usando if-then-else 8 | 9 | SOLUZIONE: 10 | *) 11 | 12 | (*A*) 13 | fun A (0) = 2 14 | | A (1) = 2 15 | | A (2) = 2 16 | | A (_) = 3; 17 | 18 | (*B*) 19 | fun B(x) = if (x>2) then 3 else if (x<0) then 3 else 2; 20 | 21 | (* ESEMPIO ESECUZIONE: *) 22 | 23 | A(0); 24 | B(0); 25 | A(2); 26 | B(2); 27 | A(~1); 28 | A(~2); 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Esercizi/esercizio02.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 2 3 | Testo: 4 | Scrivere una funzione "prod" che calcoli il prodotto di tutti gli interi tra 2 numeri m ed n. (con m >= m inclusi). 5 | Usare poi questa funzione per scrivere una funzione C(n,k) la quale calcola il numero di combinazioni di n elementi 6 | presi k a k. 7 | Definita dalla formula matematica: C(n, k) = n!/(k! * (n − k)!) 8 | che equivale anche a: C(n, k) = (n − k + 1) · (n − k + 2)· · · n/1 · 2 · · · k 9 | 10 | SOLUZIONE: 11 | *) 12 | 13 | fun prod(m,n) = if n <= m then m else n * prod(m,n-1); 14 | 15 | fun C(n,k) = prod(n-k+1,n) div prod(1,k); 16 | 17 | 18 | (* ESEMPIO ESECUZIONE: *) 19 | 20 | C(7,5); 21 | C(9,1); 22 | C(4,3); -------------------------------------------------------------------------------- /Esercizi/esercizio04.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 4 3 | Testo: 4 | La radice quadrata intera positiva di un numero intero non negativo è una funzione 5 | introot tale che "introot m" è il più grande intero tale che n * n è minore 6 | pari o uguale a m. Definire questa funzione in ML. 7 | 8 | es. introot 15 9 | 3*3 = 9 <= 15 --> return 3 10 | es. introot 16 11 | 4*4 = 16 <= 16 --> return 4 12 | 13 | SOLUZIONE: 14 | *) 15 | 16 | fun introot m = 17 | let 18 | fun aux(k,m) = if k*k > m then k-1 else aux(k+1,m) 19 | in 20 | aux(0,m) 21 | end; 22 | 23 | 24 | (* ESEMPIO ESECUZIONE: *) 25 | 26 | introot 15; 27 | introot 16; 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Esercizi/esercizio18.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 18 3 | Testo: 4 | Scrivere una funzione "remove_dup: ’’a list -> ’’a list" che rimuove i duplicati da una lista. 5 | 6 | SOLUZIONE: 7 | *) 8 | 9 | fun remove_dup l = 10 | let 11 | fun delete(x,[]) = [] 12 | | delete(x,y::l) = if x=y then delete(x,l) else y::delete(x,l); 13 | 14 | fun remove_dup_rec [] = [] 15 | | remove_dup_rec (x::l) = x::remove_dup_rec(delete(x,l)); 16 | in 17 | remove_dup_rec l 18 | end; 19 | 20 | (* ESEMPIO ESECUZIONE: *) 21 | 22 | remove_dup []; 23 | remove_dup [1,2,1]; 24 | remove_dup ["a","a","a"]; 25 | remove_dup [[1],[1,2],[1,2,3],[1,2],[4,5]]; 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Esercizi/esercizio17.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 17 3 | Testo: 4 | Scrivere una funzione "sumlists: int list * int list -> int list" che prende come argomenti 5 | due liste di interi e ritorna una lista formata dalla somma degli elementi nella stessa posizione. 6 | Estendere la lista più corta se necessario aggiungendo zeri. 7 | 8 | es. sumlists([1,2],[3,4]); 9 | val it = [4, 6]: int list 10 | 11 | SOLUZIONE: 12 | *) 13 | 14 | fun sumlists(nil, nil) = 0::nil 15 | | sumlists(l,[]) = l 16 | | sumlists([],k) = k 17 | | sumlists(x::l,y::k) = (x+y)::sumlists(l,k); 18 | 19 | (* ESEMPIO ESECUZIONE: *) 20 | 21 | sumlists([1,2],[3,4]); 22 | sumlists([1],[3,4,2]); 23 | sumlists([1,6],[3]); 24 | 25 | 26 | -------------------------------------------------------------------------------- /Esami/2020_02.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME febbraio 2020 3 | Testo: 4 | Scrivere una funzione f che data una lista di interi restituisca true se essa è ordinata in ordine crescente 5 | false altrimenti 6 | 7 | SOLUZIONE: 8 | *) 9 | 10 | fun f [] = true 11 | | f (a::[]) = true 12 | | f (a::b::l) = if a > b then false else f(b::l); 13 | 14 | 15 | (* OPPURE ALTRA SOLUZIONE VALIDA - presa dalle slide *) 16 | val rec f1 = fn l => 17 | if List.null l then true 18 | else if List.null (tl l) then true 19 | else (hd l <= hd (tl l)) andalso f1 (tl l); 20 | 21 | (* ESEMPIO ESECUZIONE: *) 22 | 23 | f [1,2,2,3,4]; 24 | f[3,2,1]; 25 | f[4,12,3,44,0]; 26 | 27 | f1 [1,2,2,3,4]; 28 | f1[3,2,1]; 29 | f1[4,12,3,44,0]; -------------------------------------------------------------------------------- /Esercizi/esercizio23.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 23 3 | Testo: 4 | Scrivere una funzione che riordina gli elementi di una lista utilizzando Quicksort 5 | 6 | SOLUZIONE: 7 | *) 8 | 9 | fun quick [] = [] 10 | | quick [x] = [x] 11 | | quick (a::bs) = 12 | let fun partition (left,right,[]) = (quick left) @ (a::quick right) 13 | | partition (left,right,x::xs) = if x<=a then partition(x::left, right,xs) 14 | else partition (left,x::right,xs) 15 | in partition([],[],bs) 16 | end; 17 | 18 | (* ESEMPIO ESECUZIONE: *) 19 | 20 | quick [1,2,3,4,5,0]; 21 | quick [1,8,99,2,45,678,875,3,5656,232,22,11,55,766]; 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Esami/2019_06.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2019 3 | 4 | Scrivere una funzione f di tipo int list -> int list che presa in input una lista trasformi ogni elemento "a" 5 | della lista nel seguente modo: 6 | se a >= 0 allora l'elemento "a" dovrà essere trasformato in a^2-1 7 | altrimenti l'elemento "a" dovrà essere trasformato in a^2+1 8 | 9 | ESEMPIO 10 | f [~1,2,3,0,~5,6]; 11 | dovrà dare in output: 12 | val it = [2, 3, 8, ~1, 26, 35]: int list 13 | 14 | SOLUZIONE: 15 | *) 16 | 17 | fun f [] = [] 18 | | f (a::b) = if (a>=0) then ((a*a)-1)::(f b) else ((a*a)+1)::(f b); 19 | 20 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 21 | 22 | f [~1,2,3,0,~5,6]; 23 | f [0,~1]; -------------------------------------------------------------------------------- /Esami/2018_06.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2018 3 | Si scriva una funzione conta (avente tipo ''a list -> int) che riceve come argomento una lista di ''a l. 4 | La funzione conta ritorna il numero di elementi della lista senza considerare i duplicati. 5 | 6 | SOLUZIONE: 7 | *) 8 | 9 | val rec conta = fn [] => 0 10 | | a::b => if (List.exists ((fn y => a = y)) b) then (conta b) else 1+(conta b); 11 | 12 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 13 | 14 | conta ["pera", "pera", "pera", "pera"]; 15 | conta ["red", "red", "green", "blue"]; 16 | conta ["red"]; 17 | conta []; 18 | conta [1,2,4,5,6,0,1,4,5]; 19 | conta [true, false, true, false]; 20 | conta [#"A",#"a",#"B",#"b"]; -------------------------------------------------------------------------------- /Esami/2021_02.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME febbraio 2021 3 | Implementare una funzione "f" che data una lista [a1,...,an], calcoli a1-a2+a3-a4+... 4 | La funzione così definita dovrà funzionare con liste di qualsiasi lunghezza. 5 | 6 | SOLUZIONE: 7 | *) 8 | 9 | fun f [] = 0 10 | | f (a::[]) = a 11 | | f (a::b::[]) = a - b 12 | | f (a::b::l) = a - b + f(l); 13 | 14 | (* SOLUZIONE ALTERNATIVA *) 15 | val f = let 16 | fun diff(x:int, y:int) = x - y; 17 | in 18 | foldr diff 0 19 | end; 20 | 21 | 22 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 23 | 24 | f []; 25 | f [1]; 26 | f [1,2]; 27 | f [1,2,3]; 28 | f [1,2,3,4]; 29 | f [3,3,3,3,3,3,3,3,3,3,3,3]; 30 | f [3,3,3,3,3,3,3,3,3,3,3,3,3]; 31 | -------------------------------------------------------------------------------- /Esercizi/esercizio11.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 11 3 | Testo: 4 | Scrivere una funzione isOrdinata che data una lista restituisca true se essa è ordinata in ordine crescente 5 | false altrimenti 6 | 7 | SOLUZIONE: 8 | *) 9 | 10 | fun isOrdinata [] = true 11 | | isOrdinata (a::[]) = true 12 | | isOrdinata (a::b::l) = if a > b then false else isOrdinata(b::l); 13 | 14 | 15 | (* OPPURE *) 16 | val rec ordered = fn l => 17 | if List.null l then true 18 | else if List.null (tl l) then true 19 | else (hd l < hd (tl l)) andalso ordered (tl l); 20 | 21 | (* ESEMPIO ESECUZIONE: *) 22 | 23 | isOrdinata [1,2,3,4]; 24 | isOrdinata[3,2,1]; 25 | isOrdinata[4,12,3,44,0]; 26 | 27 | ordered [1,2,3,4]; 28 | ordered[3,2,1]; 29 | ordered[4,12,3,44,0]; -------------------------------------------------------------------------------- /Esami/2018_08.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME agosto 2018 3 | 4 | Scrivere una funzione "prod" che calcoli il prodotto di tutti gli interi tra 2 numeri m ed n. (con m >= m inclusi). 5 | Usare poi questa funzione per scrivere una funzione Comb(n,k) la quale calcola il numero di combinazioni di n elementi 6 | presi k a k. 7 | Definita dalla formula matematica: C(n, k) = n!/(k! * (n − k)!) 8 | che equivale anche a: C(n, k) = (n − k + 1) · (n − k + 2)· · · n/1 · 2 · · · k 9 | 10 | *) 11 | 12 | fun prod(m, n) = 13 | if (n <= m) then m else n * prod(m, n-1); 14 | 15 | fun comb(n, k) = 16 | (prod(n-k+1, n)) div (prod(1, k)); 17 | 18 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 19 | 20 | comb(5,3); 21 | comb(7,5); 22 | comb(9,1); 23 | -------------------------------------------------------------------------------- /Esami/2022_07.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2022 3 | 4 | Scrivere una funzione f di tipo int list -> int list che presa in input una lista trasformi ogni elemento "a" 5 | della lista nel seguente modo: 6 | se a >= 0 allora l'elemento "a" dovrà essere trasformato in a^2-1 7 | altrimenti l'elemento "a" dovrà essere trasformato in a^2+1 8 | 9 | ESEMPIO 10 | f [~1,2,3,0,~5,6]; 11 | dovrà dare in output: 12 | val it = [2, 3, 8, ~1, 26, 35]: int list 13 | 14 | SOLUZIONE: 15 | *) 16 | 17 | fun f [] = [] 18 | | f (a::b) = if (a>=0) then ((a*a)-1)::(f b) else ((a*a)+1)::(f b); 19 | 20 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 21 | 22 | f [~1,2,3,0,~5,6]; 23 | f [0,~1]; 24 | 25 | (* NOTE: UGUALE ad esame 2019_06.sml *) -------------------------------------------------------------------------------- /Esercizi/esercizio13.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 12 3 | Testo: 4 | Scrivere una funzione isUguale che dati come argomenti 2 liste NON ordinate restituisca true se le liste 5 | sono uguali e false altrimenti 6 | 7 | SOLUZIONE: 8 | *) 9 | 10 | val rec isMember = fn (a,l) => 11 | if List.exists(fn n => n = a) l then true else false 12 | 13 | val rec containedIn = fn(l1,l2) => 14 | if null (l1) then true 15 | else isMember (hd l1,l2) andalso containedIn(tl l1,l2) ; 16 | 17 | val rec isUguale = fn l1 => fn l2 => 18 | containedIn(l1,l2) andalso containedIn (l2,l1); 19 | 20 | (* ESEMPIO ESECUZIONE: *) 21 | 22 | isUguale [] []; 23 | isUguale [1] [1]; 24 | isUguale [1,4,2,8] [8,1,4,2]; 25 | isUguale [1,2,4,3] [11,24,56,7]; 26 | isUguale [7,5,12,88] [7,88,12,5]; 27 | isUguale [7,5,12,88] [7,5,12,88,13,15]; -------------------------------------------------------------------------------- /Esami/2019_09.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME settembre 2019 3 | 4 | Scrivere una funzione chiamata f che prende in input un file "text.txt" la funzione deve ritornare la lista 5 | dei caratteri senza spazi presenti nel file di testo. 6 | 7 | Si assuma che il file sia presente nella stessa cartella. 8 | 9 | ESEMPIO 10 | Dato il file "text.txt" che contiene: 11 | ab e ad c 12 | Eseguendo il comando use "esercizio.sml"; 13 | dovrà essere prodotto il seguente risultato: 14 | val it = [#"a", #"b", #"e", #"a", #"d", #"c"]: char list 15 | 16 | SOLUZIONE: 17 | *) 18 | 19 | fun f filename = 20 | let 21 | val file = TextIO.openIn filename 22 | val str = TextIO.inputAll file 23 | in 24 | TextIO.closeIn file; 25 | List.filter (fn c => c <> #" " andalso c <> #"\t" andalso c <> #"\n") (explode str) 26 | end; 27 | f "text.txt"; -------------------------------------------------------------------------------- /Esami/2023_06.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2023 3 | 4 | scrivere una curried function “f” che prenda in input una lista di stringhe[ai, ai+1, …] e un intero n, 5 | e ritorni una lista di stringhe[bi, bi+1, …] in cui 6 | bi è uguale ad ai solo se la lunghezza di ai è minore o uguale ad n, 7 | altrimenti bi è uguale ad ai senza il primo carattere. 8 | 9 | Esempio: 10 | 11 | >f [" ", "ab", "abc", "abcd", "abcde"] 3; 12 | val it = [" ", "ab", "abc", "bcd", "bcde"]: string list 13 | 14 | SOLUZIONE: 15 | *) 16 | 17 | fun f (nil) n = nil 18 | | f (a::l) n = if (length (explode a) <= n) 19 | then 20 | a::(f (l) n) 21 | else 22 | implode(tl(explode(a)))::(f (l) n); 23 | 24 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 25 | 26 | f [" ", "ab", "abc", "abcd", "abcde"] 3; -------------------------------------------------------------------------------- /Esercizi/esercizio24.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESERCIZIO 24 3 | Testo: 4 | Leggere un file di carratteri "test.txt" contente una sequenza di parole (lettere diverse da spazi consecutive) 5 | Ritornare la lista delle parole contenute nel file. 6 | 7 | SOLUZIONE: 8 | *) 9 | 10 | fun white(" ") = true 11 | | white("\t") = true 12 | | white("\n") = true 13 | | white(_) = false; 14 | 15 | fun getWord(file) = 16 | if TextIO.endOfStream(file) then "" else 17 | let 18 | val c = TextIO.inputN(file,1) 19 | in 20 | if white(c) then "" else c^getWord(file) 21 | end; 22 | 23 | fun getList1(file) = if TextIO.endOfStream(file) then nil else getWord(file) :: getList1(file); 24 | 25 | fun getList(filename) = getList1(TextIO.openIn(filename)); 26 | 27 | (* ESEMPIO ESECUZIONE: *) 28 | 29 | getList "test.txt"; 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Esami/2020_01.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME gennaio 2020 3 | 4 | Scrivere una funzione chiamata f che prende in input un file "text2.txt" la funzione deve ritornare i caratteri 5 | in posizione pari presenti nel file txt. Il file txt conterrà un numero di caratteri pari maggiore di zero. 6 | 7 | Si assuma che il file sia presente nella stessa cartella. 8 | 9 | ESEMPIO di esecuzione 10 | Dato il file "text2.txt" che contiene: 11 | abcdef 12 | Eseguendo il comando use "esercizio.sml"; 13 | dovrà essere prodotto il seguente risultato: 14 | val it = ["b","d","f"]: string list 15 | 16 | SOLUZIONE: 17 | *) 18 | 19 | fun f filename = 20 | let 21 | val file = TextIO.openIn filename 22 | val str = TextIO.inputAll file 23 | val rec elem_pari = fn [] => [] 24 | | a::[] => [] 25 | | a::b::c => Char.toString(b)::(elem_pari c) 26 | in 27 | TextIO.closeIn file; 28 | elem_pari (explode str) 29 | end; 30 | f "text2.txt"; -------------------------------------------------------------------------------- /Esami/2016_06_T2.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2016 - TURNO 2 3 | Si scriva una funzione noduplen (avente tipo ''a list -> int) che riceve come argomento una lista di ''a l. 4 | La funzione noduplen ritorna il numero di elementi della lista senza considerare i duplicati. 5 | 6 | Come esempio, l’invocazione 7 | noduplen ["pera", "pera", "pera", "pera"]; 8 | deve avere risultato 1; 9 | noduplen ["red", "red", "green", "blue"]; 10 | deve avere risultato 3. 11 | 12 | SOLUZIONE: 13 | *) 14 | 15 | val rec noduplen = fn [] => 0 16 | | a::[] => 1 17 | | a::b => if (List.exists ((fn y => a = y)) b) then 0+(noduplen b) else 1+(noduplen b); 18 | 19 | 20 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 21 | 22 | noduplen ["pera", "pera", "pera", "pera"]; 23 | noduplen ["red", "red", "green", "blue"]; 24 | noduplen ["red"]; 25 | noduplen []; 26 | noduplen [1,2,4,5,6,0,1,4,5]; 27 | noduplen [true, false, true, false]; 28 | noduplen [#"A",#"a",#"B",#"b"]; -------------------------------------------------------------------------------- /Esami/2021_07.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2021 3 | Testo: 4 | Si scriva una funzione conta (avente tipo ' 'a list -> int) che riceve come argomento una lista di ' 'a. 5 | La funzione conta ritorna il numero di elementi della lista senza considerare i duplicati. 6 | Come esempio, l'invocazione conta ["pera", "pera", "pera", "pera"]; deve avere risultato 1, 7 | conta ["red", "red", "green", "blue"]; deve avere risultato 3 e 8 | conta [2, 3, 4, 2]; deve avere risultato 3. 9 | 10 | IMPORTANTE: notare il tipo della funzione!. 11 | 12 | SOLUZIONE: 13 | *) 14 | 15 | val rec conta = fn [] => 0 16 | | a::b => if (List.exists ((fn y => a = y)) b) then (conta b) else 1+(conta b); 17 | 18 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 19 | 20 | conta ["pera", "pera", "pera", "pera"]; 21 | conta ["red", "red", "green", "blue"]; 22 | conta ["red"]; 23 | conta []; 24 | conta [1,2,4,5,6,0,1,4,5]; 25 | conta [true, false, true, false]; 26 | conta [#"A",#"a",#"B",#"b"]; 27 | 28 | (* NOTE: UGUALE ad esame 2018_06.sml e 2020_06_T2.sml *) -------------------------------------------------------------------------------- /Esami/2016_06_T1.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2016 - TURNO 1 3 | Si scriva una funzione hist (avente tipo real list -> real * real -> int) che riceve come argomento una lista di 4 | real l ed una coppia di real (c, d). La funzione hist ritorna il numero di elementi della lista compresi 5 | nell’intervallo (c - d, c + d), estremi esclusi (vale a dire il numero di elementi r tali che (c - d < r < c + d). 6 | 7 | Come esempio, l’invocazione 8 | hist [0.1, 0.5, 1.0, 3.0, 2.5] (1.0, 0.5); 9 | deve avere risultato 1; 10 | e hist [0.1, 0.5, 1.0, 3.0, 2.5] (1.0, 0.6); 11 | deve avere risultato 2. 12 | 13 | SOLUZIONE: 14 | *) 15 | 16 | val rec hist = fn [] => (fn (c:real, d:real) => 0) 17 | | [e] => (fn (c:real, d:real) => if (e > (c-d) andalso e < (c+d)) then 1 else 0) 18 | | (e :: l) => (fn (c:real, d:real) => if (e > (c-d) andalso e < (c+d)) then 1 + hist l (c, d) else 0 + hist l (c, d)); 19 | 20 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 21 | 22 | hist [0.1, 0.5, 1.0, 3.0, 2.5] (1.0, 0.5); 23 | hist [0.1, 0.5, 1.0, 3.0, 2.5] (1.0, 0.6); 24 | hist [] (2.4, 12.6); 25 | hist [4.0] (4.1, 0.0); -------------------------------------------------------------------------------- /Esami/2017_06_T1.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2017 - Turno 1 3 | Si scriva una funzione sommali (avente tipo int -> int list -> int) che riceve come argomento un intero n ed una 4 | lista di interi l. La funzione sommali somma ad n gli elementi di l che hanno posizione pari (se la lista 5 | contiene meno di 2 elementi, sommali ritorna n). 6 | 7 | Come esempio, l’invocazione 8 | sommali 0 [1,2]; 9 | deve avere risultato 2; 10 | sommali 1 [1,2,3]; 11 | deve avere risultato 3; 12 | sommali 2 [1,2,3,4]; 13 | deve avere risultato 8. 14 | 15 | SOLUZIONE: 16 | *) 17 | 18 | fun sommali z [] = z 19 | | sommali z (a::[]) = z 20 | | sommali z (a::b::c) = b + (sommali z c); 21 | 22 | (* altro modo extra usando fn -> stesso risultato *) 23 | 24 | val rec sommali_diversa = fn z => fn [] => z 25 | | a::[] => z 26 | | a::b::c => b + (sommali z c); 27 | 28 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 29 | 30 | sommali 0 [1,2]; 31 | sommali 1 [1,2,3]; 32 | sommali 2 [1,2,3,4]; 33 | 34 | sommali_diversa 0 [1,2]; 35 | sommali_diversa 1 [1,2,3]; 36 | sommali_diversa 2 [1,2,3,4]; 37 | 38 | -------------------------------------------------------------------------------- /Esami/2024_01.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME gennaio 2024 3 | 4 | Scrivere una funzione suffixes (di tipo string -> string list) che presa in input una stringa, 5 | ritorni una lista di tutti i suffissi della stringa, compresa la stringa stessa ed esclusa la stringa vuota. 6 | (nota: esista una funzione map che permette appendere un elemento a ogni elementi da lista) 7 | 8 | Esempi: 9 | > suffixes "ciao"; 10 | val it : ["ciao" , "cia", "ci", "ci", "c"]; 11 | > suffixes ""; 12 | val it : []; 13 | > suffixes "hi world"; 14 | val it : ["hi world","hi worl","hi wor","hi wo","hi w","hi ","hi","h"]; 15 | 16 | SOLUZIONE: 17 | *) 18 | 19 | fun suffixes s = 20 | let 21 | fun helper (str, acc) = 22 | if str = "" then 23 | List.rev acc 24 | else 25 | helper (String.extract (str, 1, NONE), str :: acc) 26 | in 27 | helper (s, []) 28 | end; 29 | 30 | fun suffixesAlternative "" = [] 31 | | suffixesAlternative s = s :: suffixesAlternative (String.extract (s, 0, SOME (size s - 1))); 32 | 33 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 34 | 35 | suffixes "ciao"; 36 | suffixes ""; 37 | suffixes "hi world"; 38 | suffixes "test 123 4"; -------------------------------------------------------------------------------- /Esami/2017_02.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME febbraio 2017 3 | Si consideri una possibile implementazione degli insiemi di interi in standard ML, in cui un insieme di 4 | interi rappresentato da una funzione da int a bool: 5 | *) 6 | 7 | type insiemediinteri = int -> bool; 8 | 9 | (* 10 | La funzione applicata ad un numero intero ritorna true se il numero appartiene all’insieme, false 11 | altrimenti. L’insieme vuoto è quindi rappresentato da una funzione che ritorna sempre false: 12 | *) 13 | 14 | val vuoto:insiemediinteri = fn n => false; 15 | 16 | (* ed un intero può essere aggiunto ad un insieme tramite la funzione aggiungi: *) 17 | 18 | val aggiungi = fn f:insiemediinteri => fn x:int => (fn n:int => if (n = x) then true else false ):insiemediinteri; 19 | 20 | (* É possibile verificare se un intero è contenuto in un insieme tramite la funzione contiene: *) 21 | 22 | val contiene = fn f:insiemediinteri => fn n:int => f n; 23 | 24 | (* 25 | Si implementi la funzione unione, avente tipo insiemediinteri -> insiemediinteri -> insiemediinteri che dati 26 | due insiemi di interi ne calcola l’unione. 27 | 28 | SOLUZIONE: 29 | *) 30 | 31 | val unione = fn i1:insiemediinteri => fn i2:insiemediinteri => (fn n => ((contiene i1 n) orelse (contiene i2 n))):insiemediinteri; -------------------------------------------------------------------------------- /Esami/2016_08.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME agosto 2016 3 | Si consideri una possibile implementazione degli insiemi di interi in standard ML, in cui un insieme di 4 | interi rappresentato da una funzione da int a bool: 5 | *) 6 | 7 | type insiemediinteri = int -> bool; 8 | 9 | (* 10 | La funzione applicata ad un numero intero ritorna true se il numero appartiene all’insieme, false 11 | altrimenti. L’insieme vuoto è quindi rappresentato da una funzione che ritorna sempre false: 12 | *) 13 | 14 | val vuoto:insiemediinteri = fn n => false; 15 | 16 | (* ed un intero può essere aggiunto ad un insieme tramite la funzione aggiungi: *) 17 | 18 | val aggiungi = fn f:insiemediinteri => fn x:int => (fn n:int => if (n = x orelse f n) then true else false ):insiemediinteri; 19 | 20 | (* É possibile verificare se un intero è contenuto in un insieme tramite la funzione contiene: *) 21 | 22 | val contiene = fn f:insiemediinteri => fn n:int => f n; 23 | 24 | (* 25 | Si implementi la funzione intersezione, avente tipo insiemediinteri -> insiemediinteri -> insiemediinteri, che dati 26 | due insiemi di interi ne calcola l’intersezione. 27 | 28 | SOLUZIONE: 29 | *) 30 | 31 | val intersezione = fn i1:insiemediinteri => fn i2:insiemediinteri => (fn n => ((contiene i1 n) andalso (contiene i2 n))):insiemediinteri; 32 | -------------------------------------------------------------------------------- /Esami/2015_08.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME agosto 2015 3 | Scrivere una funzione Standard ML, chiamata elementi_pari, che ha tipo 'a list -> 'a list. La funzione riceve 4 | come parametro una a-lista e ritorna una a-lista contenente gli elementi della lista di ingresso che hanno 5 | posizione pari (il secondo elemento, il quarto elemento, etc. . . ). 6 | 7 | Per esempio 8 | elementi_pari [1,5,2,10] ritorna [5,10] 9 | 10 | Si noti inoltre che la funzione elementi_pari non deve cambiare l’ordine degli elementi della lista rispetto 11 | all’ordine della lista ricevuta come argomento (considerando l’esempio precedente, il valore ritornato deve 12 | essere [5,10], non [10,5]). Si noti che la funzione elementi_pari può usare i costruttori forniti da 13 | Standard ML per le alfa-liste, senza bisogno di definire alcun datatype o altro. 14 | 15 | SOLUZIONE: 16 | *) 17 | 18 | val rec elementi_pari = fn [] => [] 19 | | a::[] => [] 20 | | (a::b::l) => b::(elementi_pari l); 21 | 22 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 23 | 24 | elementi_pari []; (* Restituisce la lista vuota [] *) 25 | elementi_pari [1]; (* Restituisce la lista vuota [] *) 26 | elementi_pari [1,4,4,5,6]; (* Restituisce la lista vuota [4,5] *) -------------------------------------------------------------------------------- /Esami/2017_06_T2.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2017 - Turno 2 3 | Si scriva una funzione sommali (avente tipo int -> int list -> int) che riceve come argomento un intero n ed una 4 | lista di interi l. La funzione sommali somma ad n gli elementi di l che hanno posizione multipla di 3 (se la 5 | lista contiene meno di 3 elementi, sommali ritorna n). 6 | 7 | Come esempio, l’invocazione 8 | sommali 0 [1,2,3]; 9 | deve avere risultato 3, 10 | sommali 1 [1,2,3]; 11 | deve avere risultato 4: e 12 | sommali 2 [1,2,3,4,5,6]; 13 | deve avere risultato 11. 14 | 15 | SOLUZIONE: 16 | *) 17 | 18 | fun sommali z [] = z 19 | | sommali z (a::[]) = z 20 | | sommali z (a::b::[]) = z 21 | | sommali z (a::b::c::d) = c + (sommali z d); 22 | 23 | (* altro modo extra usando fn -> stesso risultato *) 24 | 25 | val rec sommali_diversa = fn z => fn [] => z 26 | | a::[] => z 27 | | a::b::[] => z 28 | | a::b::c::d => c + (sommali z d); 29 | 30 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 31 | 32 | sommali 0 [1,2,3]; 33 | sommali 1 [1,2,3]; 34 | sommali 2 [1,2,3,4,5,6]; 35 | 36 | sommali_diversa 0 [1,2,3]; 37 | sommali_diversa 1 [1,2,3]; 38 | sommali_diversa 2 [1,2,3,4,5,6]; -------------------------------------------------------------------------------- /Esami/2015_06.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2015 3 | Come noto, un numero naturale è esprimibile in base agli assiomi di Peano usando il seguente tipo di dato: 4 | *) 5 | 6 | datatype naturale = zero | successivo of naturale; 7 | 8 | (* Usando tale tipo di dato, la somma fra numeri naturali è esprimibile come: *) 9 | 10 | val rec somma = fn zero => (fn n => n) 11 | | successivo a => (fn n => successivo (somma a n)); 12 | 13 | (* 14 | Scrivere una funzione Standard ML, chiamata prodotto, che ha tipo naturale -> naturale -> naturale, 15 | che calcola il prodotto di due numeri naturali. Si noti che la funzione prodotto può usare la funzione somma nella sua implementazione. 16 | 17 | SOLUZIONE: 18 | *) 19 | 20 | val rec prodotto = fn zero => (fn b => zero) 21 | | successivo(a) => (fn b => (somma b (prodotto a b))); 22 | 23 | 24 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 25 | 26 | (* Moltiplicazione 3x3=9 *) 27 | prodotto (successivo (successivo (successivo zero))) (successivo (successivo (successivo zero))); 28 | (* Stamperà: val it = successivo (successivo (successivo (successivo (successivo (successivo (successivo (successivo (successivo zero))))))): naturale *) 29 | 30 | (* Moltiplicazione 2x0=0 *) 31 | prodotto (successivo (successivo zero)) ( zero); 32 | (* Stamperà: val it = zero: naturale *) 33 | 34 | -------------------------------------------------------------------------------- /Esami/2017_07_T1.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2017 - Turno 1 3 | Si consideri il tipo di dato FOR = For of int * (int -> int); i cui valori For(n, f) rappresentano funzioni che 4 | implementano un ciclo for come il seguente: 5 | 6 | int ciclofor (int x) { 7 | for (int i = 1; i < n; i++) { 8 | x = f(x); 9 | } 10 | } 11 | 12 | Si scriva una funzione eval (avente tipo FOR -> (int -> int)) che riceve come argomento un valore di tipo FOR e 13 | ritorna una funzione da interi ad interi che implementa il ciclo indicato qui sopra (applica n - 1 volte la 14 | funzione f all’argomento). 15 | 16 | Come esempio, se val f = fn x => x * 2, allora eval (For(3, f)) ritornerà una funzione che dato un numero i 17 | ritorna i = 8: 18 | 19 | ESEMPI ESECUZIONE: 20 | > val f = fn x => x * 2; 21 | val f = fn: int -> int 22 | > eval (For(3, f)); 23 | val it = fn: int -> int 24 | > val g = eval (For(3, f)); 25 | val g = fn: int -> int 26 | > g 5; 27 | val it = 40: int 28 | *) 29 | 30 | datatype FOR = For of int * (int -> int); 31 | val rec eval = fn For (n, f) => fn x => if (n > 0) then eval (For (n - 1, f)) (f x) else x; 32 | 33 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 34 | 35 | val f = fn x => x * 2; 36 | eval (For(3, f)); 37 | val g = eval (For(3, f)); 38 | g 5; -------------------------------------------------------------------------------- /Esami/2017_07_T2.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2017 - Turno 1 3 | Si consideri il tipo di dato FOR = For of int * (int -> int); i cui valori For(n, f) rappresentano funzioni che 4 | implementano un ciclo for come il seguente: 5 | 6 | int ciclofor (int x) { 7 | for (int i = 1; i < n; i++) { 8 | x = f(x); 9 | } 10 | } 11 | 12 | Si scriva una funzione eval (avente tipo FOR -> (int -> int)) che riceve come argomento un valore di tipo FOR e 13 | ritorna una funzione da interi ad interi che implementa il ciclo indicato qui sopra (applica n - 1 volte la 14 | funzione f all’argomento). 15 | 16 | Come esempio, se val f = fn x => x * 2, allora eval (For(3, f)) ritornerà una funzione che dato un numero i 17 | ritorna i = 4: 18 | 19 | ESEMPI ESECUZIONE: 20 | > val f = fn x => x * 2; 21 | val f = fn: int -> int 22 | > eval (For(3, f)); 23 | val it = fn: int -> int 24 | > val g = eval (For(3, f)); 25 | val g = fn: int -> int 26 | > g 5; 27 | val it = 20: int 28 | *) 29 | 30 | datatype FOR = For of int * (int -> int); 31 | val rec eval = fn For (n, f) => fn x => if (n > 1) then eval (For (n - 1, f)) (f x) else x; 32 | 33 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 34 | 35 | val f = fn x => x * 2; 36 | eval (For(3, f)); 37 | val g = eval (For(3, f)); 38 | g 5; -------------------------------------------------------------------------------- /Esami/2018_07.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2018 3 | Si consideri il tipo di dato ITER = Iter of int * (int -> int); i cui valori ITER(n, f) rappresentano funzioni che 4 | implementano un ciclo for come il seguente: 5 | 6 | int ITER (int x) { 7 | for (int i = 1; i < n; i++) { 8 | x = f(x); 9 | } 10 | } 11 | 12 | Si scriva una funzione eval (avente tipo Iter -> (int -> int)) che riceve come argomento un valore di tipo Iter e 13 | ritorna una funzione da interi ad interi che implementa il ciclo indicato qui sopra (applica n - 1 volte la 14 | funzione f all’argomento). 15 | 16 | Come esempio, se val f = fn x => x * 2, allora eval (Iter(3, f)) ritornerà una funzione che dato un numero i 17 | ritorna i = 8: 18 | 19 | ESEMPI ESECUZIONE: 20 | > val f = fn x => x * 2; 21 | val f = fn: int -> int 22 | > eval (Iter(3, f)); 23 | val it = fn: int -> int 24 | > val g = eval (Iter(3, f)); 25 | val g = fn: int -> int 26 | > g 5; 27 | val it = 40: int 28 | 29 | SOLUZIONE: 30 | *) 31 | 32 | datatype ITER = Iter of int * (int -> int); 33 | val rec eval = fn Iter (n, f) => fn x => if (n > 0) then eval (Iter (n-1, f)) (f x) else x; 34 | 35 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 36 | 37 | val f = fn x => x * 2; 38 | eval (Iter(3, f)); 39 | val g = eval (Iter(3, f)); 40 | g 5; -------------------------------------------------------------------------------- /Esami/2020_09.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME settembre 2020 3 | Si consideri il tipo di dato FOR = For of int * (int -> int); i cui valori For(n, f) rappresentano funzioni che 4 | implementano un ciclo for come il seguente: 5 | 6 | int ciclofor (int x) { 7 | for (int i = 1; i < n; i++) { 8 | x = f(x); 9 | } 10 | return x; 11 | } 12 | 13 | Si scriva una funzione eval (avente tipo FOR -> (int -> int)) che riceve come argomento un valore di tipo FOR e 14 | ritorna una funzione da interi ad interi che implementa il ciclo indicato qui sopra (applica n volte la 15 | funzione f all’argomento). 16 | 17 | Come esempio, se val f = fn x => x * 2, allora eval (For(3, f)) ritornerà una funzione che dato un numero i 18 | ritorna i * 8: 19 | 20 | ESEMPI ESECUZIONE: 21 | > val f = fn x => x * 2; 22 | val f = fn: int -> int 23 | > eval (For(3, f)); 24 | val it = fn: int -> int 25 | > val g = eval (For(3, f)); 26 | val g = fn: int -> int 27 | > g 5; 28 | val it = 40: int 29 | *) 30 | 31 | datatype FOR = For of int * (int -> int); 32 | val rec eval = fn For (n, f) => fn x => if (n > 0) then eval (For (n - 1, f)) (f x) else x; 33 | 34 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 35 | 36 | val f = fn x => x * 2; 37 | eval (For(3, f)); 38 | val g = eval (For(3, f)); 39 | g 5; 40 | 41 | (* NOTE: UGUALE ad esame 2017_07_T1.sml *) -------------------------------------------------------------------------------- /Esami/2020_06_T2.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2020 - Turno 2 3 | Testo: 4 | Si scriva una funzione conta (avente tipo ''a list -> int) che riceve come argomento una 5 | lista di ''a l. La funzione conta ritorna il numero di elementi della lista senza considerare 6 | i duplicati. 7 | 8 | Come esempio, l'invocazione 9 | conta ["pera", "pera", "pera", "pera"]; deve avere risultato 1; 10 | conta ["red", "red", "green", "blue"]; deve avere risultato 3. 11 | 12 | La funzione conta deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. 13 | Si consegni il file .sml contenente la definizione di conta. 14 | 15 | IMPORTANTE: prima di sottomettere il file usando il form sotto riportato, rinominarlo come segue: 16 | cognome del candidato, nome e matricola, separati dal carattere “_”. 17 | E.g., per Mario Rossi, matricola 1234567, il file corrispondente sarà ROSSI_MARIO_1234567.sml 18 | 19 | SOLUZIONE: 20 | *) 21 | 22 | val rec conta = fn [] => 0 23 | | a::b => if (List.exists ((fn y => a = y)) b) then (conta b) else 1+(conta b); 24 | 25 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 26 | 27 | conta ["pera", "pera", "pera", "pera"]; 28 | conta ["red", "red", "green", "blue"]; 29 | conta ["red"]; 30 | conta []; 31 | conta [1,2,4,5,6,0,1,4,5]; 32 | conta [true, false, true, false]; 33 | conta [#"A",#"a",#"B",#"b"]; 34 | 35 | (* NOTE: UGUALE ad esame 2018_06.sml *) -------------------------------------------------------------------------------- /Esami/2020_06_T1.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2020 - Turno 1 3 | Testo: 4 | Si scriva una funzione sommali (avente tipo int -> int list -> int) che riceve come argomento un intero n ed una lista di interi l. 5 | La funzione sommali somma ad n gli elementi di l che hanno posizione pari (se la lista contiene meno di 2 elementi, sommali ritorna n). 6 | 7 | Come esempio, l'invocazione 8 | 9 | sommali 0 [1,2]; 10 | deve avere risultato 2, 11 | sommali 1 [1,2,3]; 12 | deve avere risultato 3: e 13 | sommali 2 [1,2,3,4]; 14 | deve avere risultato 8. IMPORTANTE: notare il tipo della funzione!. 15 | 16 | La funzione sommali deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. 17 | Si consegni il file .sml contenente la definizione di sommali. 18 | 19 | IMPORTANTE: prima di sottomettere il file usando il form sotto riportato, rinominarlo come segue: 20 | cognome del candidato, nome e matricola, separati dal carattere “_”. 21 | E.g., per Mario Rossi, matricola 1234567, il file corrispondente sarà ROSSI_MARIO_1234567.sml 22 | 23 | SOLUZIONE: 24 | *) 25 | 26 | fun sommali z [] = z 27 | | sommali z (a::[]) = z 28 | | sommali z (a::b::c) = b + (sommali z c); 29 | 30 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) Codice di test da rimuovere alla consegna! *) 31 | 32 | sommali 0 [1,2]; 33 | sommali 1 [1,2,3]; 34 | sommali 2 [1,2,3,4]; 35 | 36 | (* NOTE: UGUALE ad esame 2017_06_T1.sml *) -------------------------------------------------------------------------------- /Esami/2022_01.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME gennaio 2022 3 | Testo: 4 | Si scriva una funzione sommali (avente tipo int -> int list -> int) che riceve come argomento un intero n ed una lista di interi l. 5 | La funzione sommali somma ad n gli elementi di l che hanno posizione pari (se la lista contiene meno di 2 elementi, sommali ritorna n). 6 | 7 | Come esempio, l'invocazione 8 | 9 | sommali 0 [1,2]; 10 | deve avere risultato 2, 11 | sommali 1 [1,2,3]; 12 | deve avere risultato 3: e 13 | sommali 2 [1,2,3,4]; 14 | deve avere risultato 8. IMPORTANTE: notare il tipo della funzione!. 15 | 16 | La funzione sommali deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. 17 | Si consegni il file .sml contenente la definizione di sommali. 18 | 19 | IMPORTANTE: prima di sottomettere il file usando il form sotto riportato, rinominarlo come segue: 20 | cognome del candidato, nome e matricola, separati dal carattere “_”. 21 | E.g., per Mario Rossi, matricola 1234567, il file corrispondente sarà ROSSI_MARIO_1234567.sml 22 | 23 | SOLUZIONE: 24 | *) 25 | 26 | fun sommali z [] = z 27 | | sommali z (a::[]) = z 28 | | sommali z (a::b::c) = b + (sommali z c); 29 | 30 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) Codice di test da rimuovere alla consegna! *) 31 | 32 | sommali 0 [1,2]; 33 | sommali 1 [1,2,3]; 34 | sommali 2 [1,2,3,4]; 35 | 36 | (* NOTE: UGUALE ad esame 2017_06_T1.sml e 2020_06_T1.sml *) -------------------------------------------------------------------------------- /Esami/2024_02.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME febbraio 2024 3 | 4 | Scrivere una funzione prefixes (di tipo string -> string list) che presa in input una stringa, 5 | ritorni una lista di tutti i prefissi della stringa, compresa la stringa stessa ed esclusa la stringa vuota. 6 | (nota: esista una funzione map che permette appendere un elemento a ogni elementi da lista) 7 | 8 | Esempi: 9 | > prefixes "ciao"; 10 | val it : ["c" , "ci", "cia", "ciao"]; 11 | > prefixes ""; 12 | val it : []; 13 | > prefixes "hi world"; 14 | val it : ["h", "hi", "hi ", "hi w", "hi wo", "hi wor", "hi worl", "hi world"]; 15 | 16 | SOLUZIONE: 17 | *) 18 | 19 | fun prefixes s = 20 | (* Helper function that generates the prefixes by using an index *) 21 | let 22 | (* Inner recursive function that constructs the prefix list *) 23 | fun helper (str, len) = 24 | if len = String.size str then 25 | [str] (* If the length equals the size of the string, return the string as the final prefix *) 26 | else 27 | String.substring(str, 0, len) :: helper (str, len + 1) 28 | in 29 | if s = "" then [] (* If the input string is empty, return an empty list *) 30 | else helper (s, 1) (* Otherwise, start generating prefixes from length 1 *) 31 | end; 32 | 33 | fun prefixesAlternative s = 34 | let 35 | fun helper (str, acc, n) = 36 | if n > String.size str then 37 | List.rev acc 38 | else 39 | helper (str, (String.substring (str, 0, n)) :: acc, n + 1) 40 | in 41 | helper (s, [], 1) 42 | end; 43 | 44 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 45 | 46 | prefixes "ciao"; 47 | prefixes ""; 48 | prefixes "hi world"; 49 | prefixes "test 123"; -------------------------------------------------------------------------------- /Esami/2017_09.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME settembre 2017 3 | Si consideri il tipo di dato 4 | *) 5 | 6 | datatype intonil = Nil | Int of int; 7 | 8 | (* ed una possibile implementazione semplificata di ambiente (che considera solo valori interi) basata su di esso: *) 9 | 10 | type ambiente = string -> intonil 11 | 12 | (* 13 | In questa implementazione, un ambiente è rappresentato da una funzione che mappa nomi (valori di tipo string) 14 | in valori di tipo intonil (che rappresentano un intero o nessun valore). Tale funzione applicata ad un nome 15 | ritorna il valore intero ad esso associato oppure Nil. Usando questa convenzione, l’ambiente vuoto (in cui 16 | nessun nome è associato a valori) può essere definito come: 17 | *) 18 | 19 | val ambientevuoto = fn _:string => Nil; 20 | 21 | (* 22 | Basandosi su queste definizioni, si definisca una funzione "lega" con tipo ambiente -> string -> int -> ambiente. 23 | che a partire da un ambiente (primo argomento) genera un nuovo ambiente (valore di ritorno) uguale al primo 24 | argomento più un legame fra il nome e l’intero ricevuti come secondo e terzo argomento. 25 | 26 | Esempio: 27 | – ((lega ambientevuoto "a"1)"a") deve ritornare Int 1; 28 | – ((lega ambientevuoto "a"1)"boh") deve ritornare Nil; 29 | – ((lega (lega ambientevuoto "a"1)"boh"~1)"boh") deve ritornare Int ~1; 30 | – ((lega (lega ambientevuoto "a"1)"boh"~1)"mah") deve ritornare Nil. 31 | 32 | SOLUZIONE: 33 | *) 34 | 35 | val lega = fn e:ambiente => fn nome => fn valore => (fn n => if (n = nome) then (Int valore) else (e n)):ambiente; 36 | 37 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 38 | 39 | ((lega ambientevuoto "a"1)"a"); 40 | ((lega ambientevuoto "a"1)"boh"); 41 | ((lega (lega ambientevuoto "a"1)"boh"~1)"boh"); 42 | ((lega (lega ambientevuoto "a"1)"boh"~1)"mah"); -------------------------------------------------------------------------------- /Esami/2018_01.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME gennaio 2018 3 | Si consideri il tipo di dato: 4 | *) 5 | datatype lambda_expr = Var of string 6 | | Lambda of string * lambda_expr 7 | | Apply of lambda_expr * lambda_expr; 8 | 9 | (* 10 | che rappresenta un’espressione del Lambda-calcolo. 11 | Il costruttore Var crea un’espressione costituita da un’unica funzione / variabile (il cui nome è un valore 12 | di tipo string); 13 | Il costruttore Lambda crea una Lambda-espressione a partire da un’altra espressione, legandone una variabile 14 | (indicata da un valore di tipo string); 15 | Il costruttore Apply crea un’espressione data dall’applicazione di un’espressione ad un’altra. 16 | 17 | Si scriva una funzione is_bound (avente tipo string -> lambda_expr -> bool) che riceve come argomenti una stringa 18 | (che rappresenta il nome di una variabile / funzione) ed una Lambda-espressione, ritornando true se la variabile 19 | indicata appare come legata nell’espressione, false altrimenti. 20 | 21 | Come esempio, l’invocazione 22 | is_bound "a" (Var "a") 23 | deve avere risultato true, l’invocazione 24 | is_bound "b" (Var "a") 25 | deve avere risultato false, l’invocazione 26 | is_bound "a" (Lambda ("a", Apply((Var "a"), Var "b"))) 27 | deve avere risultato true, l’invocazione 28 | is_bound "b" (Lambda ("a", Apply((Var "a"), Var "b"))) 29 | deve avere risultato true e così via. 30 | 31 | SOLUZIONE: 32 | *) 33 | 34 | val rec is_bound = fn s => fn Var v => s = v 35 | | Lambda (v, e) => if (s = v) then true else is_bound s e 36 | | Apply (e1, e2) => (is_bound s e1) orelse (is_bound s e2); 37 | 38 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 39 | 40 | is_bound "a" (Var "a"); 41 | is_bound "b" (Var "a"); 42 | is_bound "a" (Lambda ("a", Apply((Var "a"), Var "b"))); 43 | is_bound "b" (Lambda ("a", Apply((Var "a"), Var "b"))); -------------------------------------------------------------------------------- /Esami/2021_06.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2021 3 | 4 | Implementare una funzione "f" che, dato un file "test.txt" contenente una lista con un numero 5 | pari di caratteri restituisca una lista (type string list) di coppie di caratteri, ignorando i 6 | primi due e proponendo i successivi due iterativamente (quindi si avranno i caratteri 3,4 7 | seguiti da 7,8, e così via). 8 | 9 | Il file contenente il codice e file "test.txt" devono trovarsi nella stessa directory. Il file 10 | "test.txt" di esempio viene fornito unitamente a questo file. 11 | 12 | Un'ipotetica esecuzione del codice da bash potrebbe essere: 13 | 14 | Assicurarsi di avere il file "test.txt". 15 | Lanciare poly da terminale 16 | 17 | > use "my-code-name.sml"; 18 | val it = ["ac","ef","54",""]: string list 19 | 20 | La funzione f deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice 21 | di test sia usato. Si consegni il file .sml contente la definizione di f. Rinominare il file con 22 | cognome_nome.sml 23 | 24 | SOLUZIONE: 25 | *) 26 | 27 | fun f filename = 28 | let 29 | val file = TextIO.openIn(filename); 30 | val lista = explode (TextIO.inputAll file); 31 | fun coppie nil = [""] 32 | | coppie [_] = [""] 33 | | coppie (a::b::[]) = [""] 34 | | coppie (a::b::c::[]) = [""] 35 | | coppie (a::b::c::d::[]) = implode [c, d] :: [""] 36 | | coppie (a::b::c::d::l) = (implode [c, d]) :: coppie l; 37 | in 38 | TextIO.closeIn file; 39 | coppie lista 40 | end; 41 | f "test.txt"; 42 | 43 | (* NB: si aggiunge la stringa vuota "" per gestire i caratteri terminatori del file --> \n\r *) 44 | (* ALTRO MODO extra usando un'altra strategia -> stesso risultato *) 45 | 46 | val input = TextIO.openIn("test.txt"); 47 | fun f2 file=if TextIO.endOfStream(file) then [TextIO.inputN(file,2)] else 48 | let 49 | val trash=TextIO.inputN(file,2) 50 | val keep=TextIO.inputN(file,2) 51 | in 52 | keep::(f2 file) 53 | end; 54 | f2 input; 55 | -------------------------------------------------------------------------------- /Esami/2022_06.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2022 3 | 4 | Implementare una funzione "f" che, dato un file "test.txt" contenente una lista con un numero 5 | pari di caratteri restituisca una lista (type string list) di coppie di caratteri, ignorando i 6 | primi due e proponendo i successivi due iterativamente (quindi si avranno i caratteri 3,4 7 | seguiti da 7,8, e così via). 8 | 9 | Il file contenente il codice e file "test.txt" devono trovarsi nella stessa directory. Il file 10 | "test.txt" di esempio viene fornito unitamente a questo file. 11 | 12 | Un'ipotetica esecuzione del codice da bash potrebbe essere: 13 | 14 | Assicurarsi di avere il file "test.txt". 15 | Lanciare poly da terminale 16 | 17 | > use "my-code-name.sml"; 18 | val it = ["ac","ef","54",""]: string list 19 | 20 | La funzione f deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice 21 | di test sia usato. Si consegni il file .sml contente la definizione di f. Rinominare il file con 22 | cognome_nome.sml 23 | 24 | SOLUZIONE: 25 | *) 26 | 27 | fun f filename = 28 | let 29 | val file = TextIO.openIn(filename); 30 | val lista = explode (TextIO.inputAll file); 31 | fun coppie nil = [""] 32 | | coppie [_] = [""] 33 | | coppie (a::b::[]) = [""] 34 | | coppie (a::b::c::[]) = [""] 35 | | coppie (a::b::c::d::[]) = implode [c, d] :: [""] 36 | | coppie (a::b::c::d::l) = (implode [c, d]) :: coppie l; 37 | in 38 | TextIO.closeIn file; 39 | coppie lista 40 | end; 41 | f "test.txt"; 42 | 43 | (* NB: si aggiunge la stringa vuota "" per gestire i caratteri terminatori del file --> \n\r *) 44 | (* ALTRO MODO extra usando un'altra strategia -> stesso risultato *) 45 | 46 | val input = TextIO.openIn("test.txt"); 47 | fun f2 file=if TextIO.endOfStream(file) then [TextIO.inputN(file,2)] else 48 | let 49 | val trash=TextIO.inputN(file,2) 50 | val keep=TextIO.inputN(file,2) 51 | in 52 | keep::(f2 file) 53 | end; 54 | f2 input; 55 | 56 | (* NOTE: UGUALE ad esame 2021_06.sml *) -------------------------------------------------------------------------------- /Esami/2016_07_T1.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2016 - TURNO 1 3 | Si consideri il tipo di dato: 4 | *) 5 | datatype lambda_expr = Var of string 6 | | Lambda of string * lambda_expr 7 | | Apply of lambda_expr * lambda_expr; 8 | 9 | (* 10 | che rappresenta un’espressione del Lambda-calcolo. 11 | Il costruttore Var crea un’espressione costituita da un’unica funzione / variabile (il cui nome è un valore 12 | di tipo string); 13 | Il costruttore Lambda crea una Lambda-espressione a partire da un’altra espressione, legandone una variabile 14 | (indicata da un valore di tipo string); 15 | Il costruttore Apply crea un’espressione data dall’applicazione di un’espressione ad un’altra. 16 | 17 | Si scriva una funzione is_free (avente tipo string -> lambda_expr -> bool) che riceve come argomenti una stringa 18 | (che rappresenta il nome di una variabile / funzione) ed una Lambda-espressione, ritornando true se la variabile 19 | indicata appare come libera nell’espressione, false altrimenti (quindi, la funzione ritorna false se la variabile 20 | è legata o se non appare nell’epressione). 21 | 22 | Come esempio, l’invocazione 23 | is_free "a" (Var "a") 24 | deve avere risultato true, l’invocazione 25 | is_free "b" (Var "a") 26 | deve avere risultato false, l’invocazione 27 | is_free "a" (Lambda ("a", Apply((Var "a"), Var "b"))) 28 | deve avere risultato false, l’invocazione 29 | is_free "b" (Lambda ("a", Apply((Var "a"), Var "b"))) 30 | deve avere risultato true e così via. 31 | 32 | SOLUZIONE: 33 | *) 34 | 35 | val rec is_free = fn s => fn Var v => s = v 36 | | Lambda (v, e) => if (s = v) then false else is_free s e 37 | | Apply (e1, e2) => (is_free s e1) orelse (is_free s e2); 38 | 39 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 40 | 41 | is_free "a" (Var "a"); 42 | is_free "b" (Var "a"); 43 | is_free "a" (Lambda ("a", Apply((Var "a"), Var "b"))); 44 | is_free "b" (Lambda ("a", Apply((Var "a"), Var "b"))); -------------------------------------------------------------------------------- /Esami/2023_07.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2023 3 | 4 | Si scriva una funzione conta_duplicati (avente tipo ''a list -> (''a * int) list) che riceve come argomento una lista di ''a e restituisce una lista di tuple ''a * int. 5 | La funzione conta_duplicati ritorna una lista di coppie (elemento, numero di occorrenze dell'elemento), cioè per ogni elemento distinto e della lista di input, la lista di output contiene una coppia (e, numero di occorrenze di e). 6 | 7 | Come esempio, l'invocazione conta_duplicati [2, 2, 2, 2]; deve avere risultato [(2,4)], 8 | conta_duplicati ["lunedi'", "lunedi'", "martedi'", "lunedi'"]; deve avere risultato [("lunedi'",3), ("martedi'",1)] e 9 | conta_duplicati ["blu", "verde", "verde", "blu", "rosso"]; deve avere risultato [("blu",2), ("verde",2), ("rosso",1)]. 10 | 11 | IMPORTANTE: notare il tipo della funzione!. 12 | 13 | L'ordine delle coppie all'interno della lista risultante non è rilevante. 14 | 15 | La funzione conta_duplicati deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. 16 | Il file .sml deve contenere la chiamata a conta_duplicati. Si consegni il file .sml contenente la definizione di conta_duplicati rinominandolo Cognome_Nome_Matricola.sml. 17 | 18 | SOLUZIONE: 19 | *) 20 | 21 | fun conta_duplicati(L) = 22 | let 23 | fun estrai [] = nil 24 | | estrai (x::y) = 25 | if(List.exists(fn a => a = x) y) then 26 | estrai y 27 | else 28 | x::estrai y; 29 | 30 | val duplicati = estrai L; 31 | 32 | fun conta s [] = 0 33 | | conta s (x::y) = 34 | if s = x then 1 + conta s y 35 | else conta s y; 36 | 37 | fun tuple [] = nil 38 | | tuple (x::y) = (x, conta x L)::tuple y; 39 | 40 | in 41 | tuple duplicati 42 | end; 43 | 44 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 45 | 46 | conta_duplicati [2, 2, 2, 2]; 47 | conta_duplicati ["lunedi'", "lunedi'", "martedi'", "lunedi'"]; 48 | conta_duplicati ["blu", "verde", "verde", "blu", "rosso"]; 49 | conta_duplicati [1]; 50 | conta_duplicati [1,1,1,1,1,1,1,1,1,1]; -------------------------------------------------------------------------------- /Esami/2015_07.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2015 3 | Si consideri il seguente tipo di dato, che rappresenta una semplice espressione avente due argomenti x e y: 4 | *) 5 | datatype Expr = X 6 | | Y 7 | | Avg of Expr * Expr 8 | | Mul of Expr * Expr 9 | 10 | (* 11 | dove il costruttore X rappresenta il valore del primo argomento x dell’espressione, il costruttore Y rappresenta il 12 | valore del secondo argomento y, il costruttore Avg, che si applica ad una coppia (e1, e2), rappresenta la media 13 | (intera) dei valori di e1 ed e2, mentre il costruttore Mul (che ancora si applica ad una coppia (e1, e2)) 14 | rappresenta il prodotto dei valori di due espressioni e1 ed e2. 15 | Implementare una funzione Standard ML, chiamata compute, che ha tipo Expr -> int -> int -> int. 16 | Come suggerito dal nome, compute calcola il valore dell’espressione ricevuta come primo argomento, applicandola 17 | ai valori ricevuti come secondo e terzo argomento e ritorna un intero che indica il risultato finale della valutazione. 18 | IMPORTANTE: notare il tipo della funzione! Come si può intuire da tale tipo, la funzione riceve tre 19 | argomenti usando la tecnica del currying. É importante che la funzione abbia il tipo corretto (indicato 20 | qui sopra). Una funzione avente tipo diverso da Expr -> int -> int -> int non sarà considerata corretta. 21 | 22 | SOLUZIONE: 23 | *) 24 | 25 | val rec compute = fn X => (fn x => fn y => x) 26 | | Y => (fn x => fn y => y) 27 | | Avg(e1, e2) => (fn x => fn y => ((compute e1 x y) + (compute e2 x y)) div 2) 28 | | Mul(e1, e2) => (fn x => fn y => (compute e1 x y) * (compute e2 x y)); 29 | 30 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 31 | 32 | (compute X) 4 2; (* Restitusce 4 *) 33 | (compute Y) 4 2; (* Restitusce 2 *) 34 | compute (Avg(X,Y)) 4 2; (* Restitusce la media tra 4 e 2 = 3 *) 35 | compute (Mul(X,Y)) 4 2; (* Restitusce moltiplicazione tra 4 e 2 = 8 *) 36 | compute (Avg(X,Y)) 4 (compute (Mul(X,Y)) 4 2); (* Restitusce moltiplicazione tra 4 e 2 = 8 e poi fa la media tra 8 e 4 = 6*) -------------------------------------------------------------------------------- /Esami/2020_07.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2020 3 | Si consideri il tipo di dato 4 | *) 5 | 6 | datatype intonil = Nil | Int of int; 7 | 8 | (* ed una possibile implementazione semplificata di ambiente (che considera solo valori interi) basata su di esso: *) 9 | 10 | type ambiente = string -> intonil 11 | 12 | (* 13 | In questa implementazione, un ambiente è rappresentato da una funzione che mappa nomi (valori di tipo string) 14 | in valori di tipo intonil (che rappresentano un intero o nessun valore). Tale funzione applicata ad un nome 15 | ritorna il valore intero ad esso associato oppure Nil. Usando questa convenzione, l’ambiente vuoto (in cui 16 | nessun nome è associato a valori) può essere definito come: 17 | *) 18 | 19 | val ambientevuoto = fn _:string => Nil; 20 | 21 | (* 22 | Basandosi su queste definizioni, si definisca una funzione "lega" con tipo ambiente -> string -> int -> ambiente. 23 | che a partire da un ambiente (primo argomento) genera un nuovo ambiente (valore di ritorno) uguale al primo 24 | argomento più un legame fra il nome e l’intero ricevuti come secondo e terzo argomento. 25 | 26 | IMPORTANTE: notare il tipo della funzione! (si noti che utilizza la tecnica del currying). 27 | 28 | A titolo di esempio: 29 | 30 | – ((lega ambientevuoto "a"1)"a") deve ritornare Int 1; 31 | – ((lega ambientevuoto "a"1)"boh") deve ritornare Nil; 32 | – ((lega (lega ambientevuoto "a"1)"boh"~1)"boh") deve ritornare Int ~1; 33 | – ((lega (lega ambientevuoto "a"1)"boh"~1)"mah") deve ritornare Nil. 34 | 35 | La funzione lega deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. 36 | Non è necessario che contenga la definizione del tipo di dato intonil, di ambiente o del valore ambientevuoto. 37 | Si consegni il file .sml contenente la definizione di lega utilizzando il form qui sotto riportato. 38 | 39 | SOLUZIONE: 40 | *) 41 | 42 | val lega = fn e:ambiente => fn nome => fn valore => (fn n => if (n = nome) then (Int valore) else (e n)):ambiente; 43 | 44 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 45 | 46 | ((lega ambientevuoto "a"1)"a"); 47 | ((lega ambientevuoto "a"1)"boh"); 48 | ((lega (lega ambientevuoto "a"1)"boh"~1)"boh"); 49 | ((lega (lega ambientevuoto "a"1)"boh"~1)"mah"); 50 | 51 | (* NOTE: UGUALE ad esame 2017_09.sml *) -------------------------------------------------------------------------------- /Esami/2023_02.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME febbraio 2023 3 | Si consideri il tipo di dato 4 | *) 5 | 6 | datatype intonil = Nil | Int of int; 7 | 8 | (* ed una possibile implementazione semplificata di ambiente (che considera solo valori interi) basata su di esso: *) 9 | 10 | type ambiente = string -> intonil 11 | 12 | (* 13 | In questa implementazione, un ambiente è rappresentato da una funzione che mappa nomi (valori di tipo string) 14 | in valori di tipo intonil (che rappresentano un intero o nessun valore). Tale funzione applicata ad un nome 15 | ritorna il valore intero ad esso associato oppure Nil. Usando questa convenzione, l’ambiente vuoto (in cui 16 | nessun nome è associato a valori) può essere definito come: 17 | *) 18 | 19 | val ambientevuoto = fn _:string => Nil; 20 | 21 | (* 22 | Basandosi su queste definizioni, si definisca una funzione "lega" con tipo ambiente -> string -> int -> ambiente. 23 | che a partire da un ambiente (primo argomento) genera un nuovo ambiente (valore di ritorno) uguale al primo 24 | argomento più un legame fra il nome e l’intero ricevuti come secondo e terzo argomento. 25 | 26 | IMPORTANTE: notare il tipo della funzione! (si noti che utilizza la tecnica del currying). 27 | 28 | A titolo di esempio: 29 | 30 | – ((lega ambientevuoto "a"1)"a") deve ritornare Int 1; 31 | – ((lega ambientevuoto "a"1)"boh") deve ritornare Nil; 32 | – ((lega (lega ambientevuoto "a"1)"boh"~1)"boh") deve ritornare Int ~1; 33 | – ((lega (lega ambientevuoto "a"1)"boh"~1)"mah") deve ritornare Nil. 34 | 35 | La funzione lega deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. 36 | Non è necessario che contenga la definizione del tipo di dato intonil, di ambiente o del valore ambientevuoto. 37 | Si consegni il file .sml contenente la definizione di lega utilizzando il form qui sotto riportato. 38 | 39 | SOLUZIONE: 40 | *) 41 | 42 | val lega = fn e:ambiente => fn nome => fn valore => (fn n => if (n = nome) then (Int valore) else (e n)):ambiente; 43 | 44 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 45 | 46 | ((lega ambientevuoto "a"1)"a"); 47 | ((lega ambientevuoto "a"1)"boh"); 48 | ((lega (lega ambientevuoto "a"1)"boh"~1)"boh"); 49 | ((lega (lega ambientevuoto "a"1)"boh"~1)"mah"); 50 | 51 | (* NOTE: UGUALE ad esame 2017_09.sml e 2020_07.sml *) -------------------------------------------------------------------------------- /Esami/2024_06.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME giugno 2024 3 | 4 | L'esercizio consiste nell'implementare la funzione sum_binary di tipo int list * int list -> int list che implementa l'operazione di somma binaria. 5 | Nel programma non è permesso l'utilizzo di operatori aritmetici (+) ma si possono usare gate come andalso oppure orelse. Si possono utilizzare funzioni di supporto. 6 | Alcune chiamate di esempio: 7 | 8 | sum_binary([],[]); 9 | val it = []: int list; 10 | 11 | sum_binary([1,0],[1]); 12 | val it = [1, 1]: int list; 13 | 14 | sum_binary([1,0,0,1],[1,1,0]); 15 | val it = [1, 1, 1, 1]: int list; 16 | 17 | sum_binary([1],[1,1]); 18 | val it = [1, 0, 0]: int list; 19 | 20 | sum_binary([1,1,0,0,1,1],[1,0,1,0]); 21 | val it = [1, 1, 1, 1, 0, 1]: int list; 22 | 23 | sum_binary([1,0,0,1,1],[1,1,1,0,1]); 24 | val it = [1, 1, 0, 0, 0, 0]: int list; 25 | *) 26 | 27 | (*usato per fare la somma senza operatore +*) 28 | 29 | fun orgate (0,0) = 0 | orgate (_,_) = 1; 30 | 31 | (*i pattern match iniziali sono tutti i casi limite*) 32 | 33 | fun appo (nil,nil,true) = [1] 34 | | appo (nil,nil,false) = [0] 35 | | appo (nil,L,true) = appo([0],L,true) 36 | | appo (L,nil,true) = appo(L,[0],true) 37 | | appo (nil,L,false) = L 38 | | appo (L,nil,false) = L 39 | | appo (L,nil,_) = L 40 | (* essenzialmente se la somma genera un riporto attiva il bit di carry, poi si fa la somma effettivamente considerando il riporto se presente. Se non c'è riporto usa la funz orgate *) 41 | | appo (L1,L2,carry) = if (hd(L1) = 1 andalso hd(L2) = 1) 42 | then (if carry = true 43 | then 1::appo(tl(L1),tl(L2),true) 44 | else 0::appo(tl(L1),tl(L2),true) ) 45 | else (if carry = true 46 | then if ((hd(L1) = 1 andalso hd(L2) = 0) orelse (hd(L1) = 0 andalso hd(L2) = 1)) 47 | then 0::appo(tl(L1),tl(L2),true) 48 | else 1::appo(tl(L1),tl(L2),false) 49 | else orgate(hd(L1),hd(L2))::appo(tl(L1),tl(L2),false)); 50 | 51 | (*chiama la funzione vera e propria rovesciando la lista per fare i calcoli nell'ordine "giusto" e poi gliela restituisce per girarla di nuovo. 52 | false è il valore iniziale del riporto.*) 53 | 54 | fun sum_binary (nil,L) = L | sum_binary(L,nil) = L | sum_binary (L1,L2) = 55 | let 56 | val R1 = List.rev(L1); 57 | val R2 = List.rev(L2); 58 | in 59 | List.rev(appo(R1,R2,false)) 60 | end; 61 | 62 | (* alcune chiamate d'esempio *) 63 | 64 | sum_binary([],[]); 65 | sum_binary([1,0],[1]); 66 | sum_binary([1,0,0,1],[1,1,0]); 67 | sum_binary([1],[1,1]); 68 | sum_binary([1,1,0,0,1,1],[1,0,1,0]); 69 | sum_binary([1,0,0,1,1],[1,1,1,0,1]); -------------------------------------------------------------------------------- /Esami/2015_09.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME settembre 2015 3 | Si consideri il seguente tipo di dato: 4 | *) 5 | datatype codice = rosso of string 6 | | giallo of string 7 | | verde of string; 8 | (* 9 | che rappresenta un paziente in arrivo al pronto soccorso. 10 | La stringa rappresenta il cognome del paziente, mentre i tre diversi costruttori rosso, giallo e verde rappresentano 11 | la gravità del paziente (codice rosso: massima urgenza, codice verde: minima urgenza). 12 | Quando un paziente con codice rosso arriva al pronto soccorso, viene messo in lista d’attesa dopo tutti 13 | i pazienti con codice rosso (ma prima di quelli con codice giallo o verde); quando arriva un paziente con codice 14 | giallo, viene messo in lista d’attesa dopo tutti i pazienti con codice rosso o giallo (ma prima di quelli con 15 | codice verde), mentre quando arriva un paziente con codice verde viene messo in lista d’attesa dopo tutti gli 16 | altri pazienti. 17 | 18 | Si scriva una funzione arriva (avente tipo codice list -> codice -> codice list) che riceve come argomenti la 19 | lista dei pazienti in attesa (lista di elementi di tipo codice) ed un paziente appena arrivato (elemento di tipo 20 | codice) e ritorna la lista aggiornata dei pazienti in attesa (dopo aver inserito il nuovo paziente nel giusto posto 21 | in coda). 22 | 23 | Come esempio, l’invocazione 24 | arriva [rosso "topolino", rosso "cip", giallo "ciop", verde "paperino", verde "pluto"] (giallo "clarabella"); 25 | deve avere risultato 26 | [rosso "topolino", rosso "cip", giallo "ciop", giallo "clarabella", verde "paperino", verde "pluto"] 27 | 28 | SOLUZIONE: 29 | *) 30 | 31 | val rec arriva = fn [] => (fn x => [x]) 32 | | (verde n)::l => (fn (verde nn) => (verde n)::(arriva l (verde nn)) 33 | | x => x::((verde n)::l)) 34 | | (giallo n)::l => (fn (verde nn) => (giallo n)::(arriva l (verde nn)) 35 | | (giallo nn) => (giallo n)::(arriva l (giallo nn)) 36 | | x => x::((giallo n)::l)) 37 | | (rosso n)::l => (fn x => (rosso n)::(arriva l x)); 38 | 39 | (* Come chiamare questa funzione - NON FA PARTE DELLA SOLUZIONE DELL'ESERCIZIO (utili per capire il funzionamento) *) 40 | 41 | arriva [rosso "topolino", rosso "cip", giallo "ciop", verde "paperino", verde "pluto"] (giallo "clarabella"); 42 | arriva [] (verde "pluto"); 43 | 44 | val listaAttesa = []; 45 | val listaAttesa = arriva listaAttesa (verde "pluto"); 46 | val listaAttesa = arriva listaAttesa (verde "pippo"); 47 | val listaAttesa = arriva listaAttesa (giallo "pluto"); 48 | val listaAttesa = arriva listaAttesa (rosso "ciop"); 49 | val listaAttesa = arriva listaAttesa (verde "cip"); -------------------------------------------------------------------------------- /Esami/2016_07_T2.sml: -------------------------------------------------------------------------------- 1 | (* 2 | ESAME luglio 2016 - TURNO 2 3 | Basandosi sul tipo di dato espressione e la funzione eval definiti come segue: 4 | 5 | local 6 | val rec eval = fn costante n => n 7 | | somma (a1, a2) => (eval a1) + (eval a2) 8 | | sottrazione (a1, a2) => (eval a1) - (eval a2) 9 | | prodotto (a1, a2) => (eval a1) * (eval a2) 10 | | divisione (a1, a2) => (eval a1) div (eval a2); 11 | in 12 | val semplifica = fn costante n => costante(n) 13 | | somma (a1, a2) => costante((eval a1) + (eval a2)) 14 | | sottrazione (a1, a2) => costante((eval a1) - (eval a2)) 15 | | prodotto (a1, a2) => costante((eval a1) * (eval a2)) 16 | | divisione (a1, a2) => costante((eval a1) div (eval a2)) 17 | end; 18 | 19 | il tipo espressione può essere esteso come segue per supporare il concetto di variabile: 20 | *) 21 | 22 | datatype espressione = costante of int 23 | | variabile of string 24 | | somma of espressione * espressione 25 | | sottrazione of espressione * espressione 26 | | prodotto of espressione * espressione 27 | | divisione of espressione * espressione 28 | | var of string * espressione * espressione; 29 | 30 | (* 31 | Si riscriva la funzione eval per supportare i due nuovi costruttori variabile e var. variabile x, con 32 | x di tipo stringa, é valutata al valore della variabile di nome x (per fare questo, eval deve cercare 33 | nell’ambiente un legame fra tale nome ed un valore). var (x, e1, e2) é valutata al valore di e2 dopo 34 | aver assegnato ad x il valore di e1. 35 | Per poter valutare correttamente variabile e var, eval deve quindi ricevere come argomento l’ambiente 36 | in cui valutare le variabili. Tale ambiente può essere rappresentato come una lista di coppie (stringa, 37 | intero) ed avra’ quindi tipo (string * int)list. 38 | La funzione eval deve quindi avere tipo (string * int)list -> espressione -> int. 39 | 40 | SOLUZIONE: 41 | *) 42 | 43 | local 44 | val rec cerca = fn s => fn [] => 0 45 | | (s1, v)::l => if s1 = s then v else cerca s l 46 | in 47 | val rec eval = fn env => fn costante n => n 48 | | variabile s => cerca s env 49 | | somma (a1, a2) => (eval env a1) + (eval env a2) 50 | | sottrazione (a1, a2) => (eval env a1) - (eval env a2) 51 | | prodotto (a1, a2) => (eval env a1) * (eval env a2) 52 | | divisione (a1, a2) => (eval env a1) div (eval env a2) 53 | | var (v, e1, e2) => eval ((v, eval env e1)::env) e2 54 | end; 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## UNITN programmazione funzionale - SML 2 | 3 | ![Stars](https://img.shields.io/github/stars/pater999/UNITN-linguaggi-programmazione-SML.svg) ![Release](https://img.shields.io/github/release/pater999/UNITN-linguaggi-programmazione-SML.svg) ![Downloads](https://img.shields.io/github/downloads/pater999/UNITN-linguaggi-programmazione-SML/total.svg) ![Pull Requests](https://img.shields.io/github/issues-pr-closed/pater999/UNITN-linguaggi-programmazione-SML.svg) ![Forks](https://img.shields.io/github/forks/pater999/UNITN-linguaggi-programmazione-SML.svg) ![Made with markdown](https://img.shields.io/badge/Made%20with-Markdown-1f425f.svg) ![Maintained](https://img.shields.io/badge/Maintained%3F-yes-green.svg) 4 | 5 | Repository contenente alcuni esami con soluzione proposti durante lo sbarramento dell'esame di Programmazione Funzionale (Ex. Linguaggi di programmazione modulo 2) tenuto dai prof Kuper e Di Francescomarino all'Università di Trento. 6 | 7 | ## Consigli per prepararsi al meglio 8 | 9 | - Iniziate leggendo il [PDF ML for dummies](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/blob/master/ML%20for%20Dummies.pdf) 10 | - Guardatevi questi [video tutorial](https://www.youtube.com/playlist?list=PL-eVNDa9MNJczU4ZjhJDT8rIcCa12DyAx) (in inglese ma ben fatti - bastano i primi 10/11) 11 | - Provate a fare gli esercizi che trovate nella [cartella Esercizi](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/tree/master/Esercizi). 12 | - Provate a fare gli esami passati che trovate nella [cartella Esami](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/tree/master/Esami) o raccolti in [questo file](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/blob/master/Esami/Esami.md). 13 | Gli esami di Kuper sono (_fino a questo momento_) più **semplici** rispetto quelli degli anni precedenti e si **ripetono spesso**. 14 | - _FACOLTATIVO:_ leggetevi velocemente le slide del corso. 15 | - Tutte le risorse presenti in questa repository sono scaricabili a [questo link](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/releases). 16 | 17 | ### Piccola guida PolyML 18 | 19 | **INSTALLAZIONE SU WINDOWS** 20 | 21 | - Scaricate ed eseguite PolyML5.8-64bit.msi da [qui](https://github.com/polyml/polyml/releases). 22 | - Una volta installato vi basterà aprirlo e si aprirà il terminale di polyML. 23 | 24 | **INSTALLAZIONE SU LINUX** 25 | 26 | - Aprite il terminale e digitate `sudo apt-get update` e poi `sudo apt-get install polyml` 27 | - Una volta installato digitate `poly` e vi si aprirà il terminale di polyML. 28 | 29 | _Consiglio di utilizzare Linux che è più comodo rispetto a Windows ed è quello utilizzato durante l'esame._
30 | 31 | **COMANDI UTILI** 32 | 33 | - Per aprire un file all'interno della console di POLY basta scrivere `use "nomefile.sml";` 34 | - Per visualizzare tutte le funzioni di una libreria utilizzate il comando `open ;` (es. `open TextIO;`) 35 | - Per copiare ed incollare testo sul terminale di poly dovete installare rlwrap utilizzando il comando `sudo apt install rlwrap` e poi avviare poly con il comando `rlwrap poly`. Sarete così in grado di copiare testo e accedere alla storia dei comandi utilizzando la freccia in alto. 36 | 37 | **LIBRERIE IMPORTANTI** 38 | 39 | Qui sotto la [lista delle librerie](https://www.itu.dk/~sestoft/mosmllib/index.html) più importanti con relativa documentazione (qualsiasi libreria è utilizzabile durante l'esame): 40 | 41 | - [List](https://www.itu.dk/~sestoft/mosmllib/List.html) 42 | - [TextIO](https://www.itu.dk/~sestoft/mosmllib/TextIO.html) 43 | - [Int](https://www.itu.dk/~sestoft/mosmllib/Int.html) 44 | - [String](https://www.itu.dk/~sestoft/mosmllib/String.html) 45 | - [Char](https://www.itu.dk/~sestoft/mosmllib/Char.html) 46 | - [Math](https://www.itu.dk/~sestoft/mosmllib/Math.html) 47 | 48 | ### Data aggiornamento 49 | Questa repository è aggiornata all'esame di **giugno 2024**. 50 | ## Parte teorica - 2° Parte dell'esame 51 | 52 | Trovate una repository utile per preparare la parte teorica a [questo link](https://github.com/Pater999/UNITN-lingprog-simulatore-mod2). Essa comprende un simulatore web con le domande prese dagli esami passati (che spesso si sono rivelate **uguali o simili** negli esami recenti). 53 | 54 | ## Nuovi esami 55 | 56 | Gli esami **non** vengono più pubblicati dal professore. L'unico modo per mantenere questa repository aggiornata è ricordarsi il testo e pubblicarlo qui. Aprendo un [issue](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/issues), una [pull request](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/pulls) oppure contattandomi su [telegram](https://t.me/pater999) scrivendomi il testo dell'esame svolto. Facendo ciò sarete sicuramente utili agli studenti degli anni successivi. A tal proposito ringrazio **tutti** quelli che hanno contribuito a mantenere questa repository aggiornata! -------------------------------------------------------------------------------- /Esami/Esami.md: -------------------------------------------------------------------------------- 1 | ## Raccolta esami SML con soluzione (Programmazione funzionale, UNITN, prof. Kuper | Di Francescomarino) 2 | 3 | Questi appunti sono stati creati da [Pater999](https://github.com/Pater999) con la gentile collaborazione di altri studenti degli anni successivi. 4 | Altri appunti/esercizi/esami/consigli si possono trovare [in questa repository github](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML). 5 | L'ultima versione di questo file è scaricabile al [seguente link](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/releases). 6 | Prima di leggere questo file consiglio di leggere il [seguente Readme](https://github.com/Pater999/UNITN-linguaggi-programmazione-SML/blob/master/README.md). 7 | 8 | ## Indice esami 9 | 10 | - [Giugno 2015](#esame-giugno-2015) 11 | - [Luglio 2015](#esame-luglio-2015) 12 | - [Agosto 2015](#esame-agosto-2015) 13 | - [Settembre 2015](#esame-settembre-2015) 14 | - [Giugno 2016](#esame-giugno-2016) 15 | - [Turno 1](#turno-1-g2016) 16 | - [Turno 2](#turno-2-g2016) 17 | - [Luglio 2016](#esame-luglio-2016) 18 | - [Turno 1](#turno-1-l2016) 19 | - [Turno 2](#turno-2-l2016) 20 | - [Agosto 2016](#esame-agosto-2016) 21 | - [Febbraio 2017](#esame-febbraio-2017) 22 | - [Giugno 2017](#esame-giugno-2017) 23 | - [Turno 1](#turno-1-g2017) 24 | - [Turno 2](#turno-2-g2017) 25 | - [Luglio 2017](#esame-luglio-2017) 26 | - [Turno 1](#turno-1-l2017) 27 | - [Turno 2](#turno-2-l2017) 28 | - [Settembre 2017](#esame-settembre-2017) 29 | - [Gennaio 2018](#esame-gennaio-2018) 30 | - [Giugno 2018](#esame-giugno-2018) 31 | - [Luglio 2018](#esame-luglio-2018) 32 | - [Agosto 2018](#esame-agosto-2018) 33 | - [Giugno 2019](#esame-giugno-2019) 34 | - [Luglio 2019](#esame-luglio-2019) 35 | - [Settembre 2019](#esame-settembre-2019) 36 | - [Gennaio 2020](#esame-gennaio-2020) 37 | - [Febbraio 2020](#esame-febbraio-2020) 38 | - [Giugno 2020](#esame-giugno-2020) 39 | - [Turno 1](#turno-1-g2020) 40 | - [Turno 2](#turno-2-g2020) 41 | - [Luglio 2020](#esame-luglio-2020) 42 | - [Settembre 2020](#esame-settembre-2020) 43 | - [Febbraio 2021](#esame-febbraio-2021) 44 | - [Giugno 2021](#esame-giugno-2021) 45 | - [Luglio 2021](#esame-luglio-2021) 46 | - [Gennaio 2022](#esame-gennaio-2022) 47 | - [Giugno 2022](#esame-giugno-2022) 48 | - [Luglio 2022](#esame-luglio-2022) 49 | - [Febbraio 2023](#esame-febbraio-2023) 50 | - [Giugno 2023](#esame-giugno-2023) 51 | - [Luglio 2023](#esame-luglio-2023) 52 | - [Gennaio 2024](#esame-gennaio-2024) 53 | - [Febbraio 2024](#esame-febbraio-2024) 54 | - [Giugno 2024](#esame-giugno-2024) 55 | 56 | ### Esame giugno 2015 57 | 58 | ##### Testo 59 | 60 | Come noto, un numero naturale è esprimibile in base agli assiomi di Peano usando il seguente tipo di dato: 61 | 62 | ``` 63 | datatype naturale = zero | successivo of naturale; 64 | ``` 65 | 66 | Usando tale tipo di dato, la somma fra numeri naturali è esprimibile come: 67 | 68 | ``` 69 | val rec somma = fn zero => (fn n => n) 70 | | successivo a => (fn n => successivo (somma a n)); 71 | ``` 72 | 73 | Scrivere una funzione Standard ML, chiamata **prodotto**, che ha tipo `naturale -> naturale -> naturale`, che calcola il prodotto di due numeri naturali. Si noti che la funzione **prodotto** può usare la funzione somma nella sua implementazione. 74 | 75 | ##### Soluzione 76 | 77 | ``` 78 | val rec prodotto = fn zero => (fn b => zero) 79 | | successivo(a) => (fn b => (somma b (prodotto a b))); 80 | ``` 81 | 82 | ##### Testing (Non fa parte della soluzione - utile per capire) 83 | 84 | _Moltiplicazione 3x3=9_ 85 | 86 | ``` 87 | prodotto (successivo (successivo (successivo zero))) (successivo (successivo (successivo zero))); 88 | ``` 89 | 90 | _Stamperà a video:_ 91 | `val it = successivo (successivo (successivo (successivo (successivo (successivo (successivo (successivo (successivo zero))))))): naturale` 92 | 93 | _Moltiplicazione 2x0=0_ 94 | `prodotto (successivo (successivo zero)) ( zero);` 95 | _Stamperà a video_: 96 | `val it = zero: naturale` 97 | 98 | ### Esame luglio 2015 99 | 100 | ##### Testo 101 | 102 | Si consideri il seguente tipo di dato, che rappresenta una semplice espressione avente due argomenti x e y: 103 | 104 | ``` 105 | datatype Expr = X 106 | | Y 107 | | Avg of Expr * Expr 108 | | Mul of Expr * Expr 109 | ``` 110 | 111 | dove il costruttore X rappresenta il valore del primo argomento x dell'espressione, il costruttore Y rappresenta il valore del secondo argomento y, il costruttore Avg, che si applica ad una coppia (e1, e2), rappresenta la media (intera) dei valori di e1 ed e2, mentre il costruttore Mul (che ancora si applica ad una coppia (e1, e2)) rappresenta il prodotto dei valori di due espressioni e1 ed e2. 112 | Implementare una funzione Standard ML, chiamata **compute**, che ha tipo `Expr -> int -> int -> int`. 113 | Come suggerito dal nome, **compute** calcola il valore dell'espressione ricevuta come primo argomento, applicandola ai valori ricevuti come secondo e terzo argomento e ritorna un intero che indica il risultato finale della valutazione. 114 | **IMPORTANTE**: notare il tipo della funzione! Come si può intuire da tale tipo, la funzione riceve tre argomenti usando la tecnica del currying. É importante che la funzione abbia il tipo corretto (indicato qui sopra). Una funzione avente tipo diverso da `Expr -> int -> int -> int` non sarà considerata corretta. 115 | 116 | ##### Soluzione 117 | 118 | ``` 119 | val rec compute = fn X => (fn x => fn y => x) 120 | | Y => (fn x => fn y => y) 121 | | Avg(e1, e2) => (fn x => fn y => ((compute e1 x y) + (compute e2 x y)) div 2) 122 | | Mul(e1, e2) => (fn x => fn y => (compute e1 x y) * (compute e2 x y)); 123 | ``` 124 | 125 | ##### Testing (Non fa parte della soluzione - utile per capire) 126 | 127 | ``` 128 | (compute X) 4 2; (* Restitusce 4 *) 129 | (compute Y) 4 2; (* Restitusce 2 *) 130 | compute (Avg(X,Y)) 4 2; (* Restitusce la media tra 4 e 2 = 3 *) 131 | compute (Mul(X,Y)) 4 2; (* Restitusce moltiplicazione tra 4 e 2 = 8 *) 132 | compute (Avg(X,Y)) 4 (compute (Mul(X,Y)) 4 2); (* Restitusce moltiplicazione tra 4 e 2 = 8 e poi fa la media tra 8 e 4 = 6*) 133 | ``` 134 | 135 | ##### 136 | 137 | ### Esame agosto 2015 138 | 139 | ##### Testo 140 | 141 | Scrivere una funzione Standard ML, chiamata **elementi_pari**, che ha tipo `'a list -> 'a list`. La funzione riceve come parametro una `a-lista` e ritorna una `a-lista` contenente gli elementi della lista di ingresso che hanno posizione pari (il secondo elemento, il quarto elemento, etc. . . ). 142 | Per esempio 143 | `elementi_pari [1,5,2,10]` ritorna `[5,10]` 144 | 145 | Si noti inoltre che la funzione **elementi_pari** non deve cambiare l'ordine degli elementi della lista rispetto all'ordine della lista ricevuta come argomento (considerando l'esempio precedente, il valore ritornato deve essere `[5,10]`, non `[10,5]`). Si noti che la funzione **elementi_pari** può usare i costruttori forniti da Standard ML per le alfa-liste, senza bisogno di definire alcun datatype o altro. 146 | 147 | ##### Soluzione 148 | 149 | ``` 150 | val rec elementi_pari = fn [] => [] 151 | | a::[] => [] 152 | | (a::b::l) => b::(elementi_pari l); 153 | ``` 154 | 155 | ##### Testing (Non fa parte della soluzione - utile per capire) 156 | 157 | ``` 158 | elementi_pari []; (* Restituisce la lista vuota [] *) 159 | elementi_pari [1]; (* Restituisce la lista vuota [] *) 160 | elementi_pari [1,4,4,5,6]; (* Restituisce la lista vuota [4,5] *) 161 | ``` 162 | 163 | ### Esame settembre 2015 164 | 165 | ##### Testo 166 | 167 | Si consideri il seguente tipo di dato: 168 | 169 | ``` 170 | datatype codice = rosso of string 171 | | giallo of string 172 | | verde of string; 173 | ``` 174 | 175 | che rappresenta un paziente in arrivo al pronto soccorso. 176 | La stringa rappresenta il cognome del paziente, mentre i tre diversi costruttori rosso, giallo e verde rappresentano la gravità del paziente (codice rosso: massima urgenza, codice verde: minima urgenza). 177 | Quando un paziente con codice rosso arriva al pronto soccorso, viene messo in lista d'attesa dopo tutti i pazienti con codice rosso (ma prima di quelli con codice giallo o verde); quando arriva un paziente con codice giallo, viene messo in lista d'attesa dopo tutti i pazienti con codice rosso o giallo (ma prima di quelli con codice verde), mentre quando arriva un paziente con codice verde viene messo in lista d'attesa dopo tutti gli altri pazienti. 178 | 179 | Si scriva una funzione **arriva** (avente tipo codice `list -> codice -> codice list`) che riceve come argomenti la lista dei pazienti in attesa (lista di elementi di tipo codice) ed un paziente appena arrivato (elemento di tipo codice) e ritorna la lista aggiornata dei pazienti in attesa (dopo aver inserito il nuovo paziente nel giusto posto in coda). 180 | 181 | Come esempio, l'invocazione: 182 | `arriva [rosso "topolino", rosso "cip", giallo "ciop", verde "paperino", verde "pluto"] (giallo "clarabella");` 183 | deve avere risultato 184 | `[rosso "topolino", rosso "cip", giallo "ciop", giallo "clarabella", verde "paperino", verde "pluto"]` 185 | 186 | ##### Soluzione 187 | 188 | ``` 189 | val rec arriva = fn [] => (fn x => [x]) 190 | | (verde n)::l => (fn (verde nn) => (verde n)::(arriva l (verde nn)) 191 | | x => x::((verde n)::l)) 192 | | (giallo n)::l => (fn (verde nn) => (giallo n)::(arriva l (verde nn)) 193 | | (giallo nn) => (giallo n)::(arriva l (giallo nn)) 194 | | x => x::((giallo n)::l)) 195 | | (rosso n)::l => (fn x => (rosso n)::(arriva l x)); 196 | ``` 197 | 198 | ##### Testing (Non fa parte della soluzione - utile per capire) 199 | 200 | ``` 201 | arriva [rosso "topolino", rosso "cip", giallo "ciop", verde "paperino", verde "pluto"] (giallo "clarabella"); 202 | arriva [] (verde "pluto"); 203 | 204 | val listaAttesa = []; 205 | val listaAttesa = arriva listaAttesa (verde "pluto"); 206 | val listaAttesa = arriva listaAttesa (verde "pippo"); 207 | val listaAttesa = arriva listaAttesa (giallo "pluto"); 208 | val listaAttesa = arriva listaAttesa (rosso "ciop"); 209 | val listaAttesa = arriva listaAttesa (verde "cip"); 210 | ``` 211 | 212 | ### Esame giugno 2016 213 | 214 | #### Turno 1 G2016 215 | 216 | ##### Testo 217 | 218 | Si scriva una funzione **hist** (`avente tipo real list -> real * real -> int`) che riceve come argomento una lista di real l ed una coppia di real (c, d). La funzione **hist** ritorna il numero di elementi della lista compresi nell'intervallo (c - d, c + d), estremi esclusi (vale a dire il numero di elementi r tali che (c - d < r < c + d). 219 | 220 | Come esempio, l'invocazione 221 | `hist [0.1, 0.5, 1.0, 3.0, 2.5] (1.0, 0.5);` 222 | deve avere risultato 1; 223 | e `hist [0.1, 0.5, 1.0, 3.0, 2.5] (1.0, 0.6);` 224 | deve avere risultato 2. 225 | 226 | ##### Soluzione 227 | 228 | ``` 229 | val rec hist = fn [] => (fn (c:real, d:real) => 0) 230 | | [e] => (fn (c:real, d:real) => if (e > (c-d) andalso e < (c+d)) then 1 else 0) 231 | | (e :: l) => (fn (c:real, d:real) => if (e > (c-d) andalso e < (c+d)) then 1 + hist l (c, d) else 0 + hist l (c, d)); 232 | ``` 233 | 234 | ##### Testing (Non fa parte della soluzione - utile per capire) 235 | 236 | ``` 237 | hist [0.1, 0.5, 1.0, 3.0, 2.5] (1.0, 0.5); 238 | hist [0.1, 0.5, 1.0, 3.0, 2.5] (1.0, 0.6); 239 | hist [] (2.4, 12.6); 240 | hist [4.0] (4.1, 0.0); 241 | ``` 242 | 243 | #### Turno 2 G2016 244 | 245 | ##### Testo 246 | 247 | Si scriva una funzione **noduplen** (avente tipo `''a list -> int`) che riceve come argomento una lista di ''a l. La funzione **noduplen** ritorna il numero di elementi della lista senza considerare i duplicati. 248 | 249 | Come esempio, l'invocazione 250 | `noduplen ["pera", "pera", "pera", "pera"];` 251 | deve avere risultato 1; 252 | `noduplen ["red", "red", "green", "blue"];` 253 | deve avere risultato 3. 254 | 255 | ##### Soluzione 256 | 257 | ``` 258 | val rec noduplen = fn [] => 0 259 | | a::[] => 1 260 | | a::b => if (List.exists ((fn y => a = y)) b) then 0+(noduplen b) else 1+(noduplen b); 261 | ``` 262 | 263 | ##### Testing (Non fa parte della soluzione - utile per capire) 264 | 265 | ``` 266 | noduplen ["pera", "pera", "pera", "pera"]; 267 | noduplen ["red", "red", "green", "blue"]; 268 | noduplen ["red"]; 269 | noduplen []; 270 | noduplen [1,2,4,5,6,0,1,4,5]; 271 | noduplen [true, false, true, false]; 272 | noduplen [#"A",#"a",#"B",#"b"]; 273 | ``` 274 | 275 | ### Esame luglio 2016 276 | 277 | #### Turno 1 L2016 278 | 279 | ##### Testo 280 | 281 | Si consideri il tipo di dato: 282 | 283 | ``` 284 | datatype lambda_expr = Var of string 285 | | Lambda of string * lambda_expr 286 | | Apply of lambda_expr * lambda_expr; 287 | ``` 288 | 289 | che rappresenta un'espressione del Lambda-calcolo. 290 | Il costruttore Var crea un'espressione costituita da un'unica funzione / variabile (il cui nome è un valore di tipo string); Il costruttore Lambda crea una Lambda-espressione a partire da un'altra espressione, legandone una variabile (indicata da un valore di tipo string); Il costruttore Apply crea un'espressione data dall'applicazione di un'espressione ad un'altra. 291 | 292 | Si scriva una funzione **is_free** (avente tipo `string -> lambda_expr -> bool`) che riceve come argomenti una stringa (che rappresenta il nome di una variabile / funzione) ed una Lambda-espressione, ritornando true se la variabile indicata appare come libera nell'espressione, false altrimenti (quindi, la funzione ritorna false se la variabile è legata o se non appare nell'espressione). 293 | 294 | Come esempio, l'invocazione 295 | `is_free "a" (Var "a")` 296 | deve avere risultato true, l'invocazione 297 | `is_free "b" (Var "a")` 298 | deve avere risultato false, l'invocazione 299 | `is_free "a" (Lambda ("a", Apply((Var "a"), Var "b")))` 300 | deve avere risultato false, l'invocazione 301 | `is_free "b" (Lambda ("a", Apply((Var "a"), Var "b")))` 302 | deve avere risultato true e così via. 303 | 304 | ##### Soluzione 305 | 306 | ``` 307 | val rec is_free = fn s => fn Var v => s = v 308 | | Lambda (v, e) => if (s = v) then false else is_free s e 309 | | Apply (e1, e2) => (is_free s e1) orelse (is_free s e2); 310 | ``` 311 | 312 | ##### Testing (Non fa parte della soluzione - utile per capire) 313 | 314 | ``` 315 | is_free "a" (Var "a"); 316 | is_free "b" (Var "a"); 317 | is_free "a" (Lambda ("a", Apply((Var "a"), Var "b"))); 318 | is_free "b" (Lambda ("a", Apply((Var "a"), Var "b"))); 319 | ``` 320 | 321 | #### Turno 2 L2016 322 | 323 | ##### Testo 324 | 325 | Basandosi sul tipo di dato espressione e la funzione **eval** definiti come segue: 326 | 327 | ``` 328 | local 329 | val rec eval = fn costante n => n 330 | | somma (a1, a2) => (eval a1) + (eval a2) 331 | | sottrazione (a1, a2) => (eval a1) - (eval a2) 332 | | prodotto (a1, a2) => (eval a1) * (eval a2) 333 | | divisione (a1, a2) => (eval a1) div (eval a2); 334 | in 335 | val semplifica = fn costante n => costante(n) 336 | | somma (a1, a2) => costante((eval a1) + (eval a2)) 337 | | sottrazione (a1, a2) => costante((eval a1) - (eval a2)) 338 | | prodotto (a1, a2) => costante((eval a1) * (eval a2)) 339 | | divisione (a1, a2) => costante((eval a1) div (eval a2)) 340 | end; 341 | ``` 342 | 343 | il tipo espressione può essere esteso come segue per supportare il concetto di variabile: 344 | 345 | ``` 346 | datatype espressione = costante of int 347 | | variabile of string 348 | | somma of espressione * espressione 349 | | sottrazione of espressione * espressione 350 | | prodotto of espressione * espressione 351 | | divisione of espressione * espressione 352 | | var of string * espressione * espressione; 353 | ``` 354 | 355 | Si riscriva la funzione **eval** per supportare i due nuovi costruttori _variabile e var_. Variabile x, con x di tipo stringa, é valutata al valore della variabile di nome x (per fare questo, eval deve cercare nell'ambiente un legame fra tale nome ed un valore). Var (x, e1, e2) é valutata al valore di e2 dopo aver assegnato ad x il valore di e1. 356 | Per poter valutare correttamente variabile e var, **eval** deve quindi ricevere come argomento l'ambiente in cui valutare le variabili. Tale ambiente può essere rappresentato come una lista di coppie `(stringa, intero)` ed avrà quindi tipo `(string, int)list`. 357 | La funzione **eval** deve quindi avere tipo `(string, int)list -> espressione -> int`. 358 | 359 | ##### Soluzione 360 | 361 | ``` 362 | local 363 | val rec cerca = fn s => fn [] => 0 364 | | (s1, v)::l => if s1 = s then v else cerca s l 365 | in 366 | val rec eval = fn env => fn costante n => n 367 | | variabile s => cerca s env 368 | | somma (a1, a2) => (eval env a1) + (eval env a2) 369 | | sottrazione (a1, a2) => (eval env a1) - (eval env a2) 370 | | prodotto (a1, a2) => (eval env a1) * (eval env a2) 371 | | divisione (a1, a2) => (eval env a1) div (eval env a2) 372 | | var (v, e1, e2) => eval ((v, eval env e1)::env) e2 373 | end; 374 | ``` 375 | 376 | ### Esame agosto 2016 377 | 378 | ##### Testo 379 | 380 | Si consideri una possibile implementazione degli insiemi di interi in standard ML, in cui un insieme di interi rappresentato da una funzione da int a bool: 381 | 382 | `type insiemediinteri = int -> bool;` 383 | 384 | La funzione applicata ad un numero intero ritorna true se il numero appartiene all'insieme, false altrimenti. L'insieme vuoto è quindi rappresentato da una funzione che ritorna sempre false: 385 | 386 | `val vuoto:insiemediinteri = fn n => false;` 387 | 388 | ed un intero può essere aggiunto ad un insieme tramite la funzione aggiungi: 389 | 390 | ``` 391 | val aggiungi = fn f:insiemediinteri => fn x:int => (fn n:int => if (n = x) 392 | then true 393 | else false):insiemediinteri; 394 | ``` 395 | 396 | É possibile verificare se un intero è contenuto in un insieme tramite la funzione contiene: 397 | 398 | `val contiene = fn f:insiemediinteri => fn n:int => f n;` 399 | 400 | Si implementi la funzione **intersezione**, avente tipo `insiemediinteri -> insiemediinteri -> insiemediinteri`, che dati due insiemi di interi ne calcola l'intersezione. 401 | 402 | ##### Soluzione 403 | 404 | ``` 405 | val intersezione = fn i1:insiemediinteri => fn i2:insiemediinteri => (fn n => ((contiene i1 n) andalso (contiene i2 n))):insiemediinteri; 406 | ``` 407 | 408 | ### Esame febbraio 2017 409 | 410 | ##### Testo 411 | 412 | Si consideri una possibile implementazione degli insiemi di interi in standard ML, in cui un insieme di interi rappresentato da una funzione da int a bool: 413 | 414 | `type insiemediinteri = int -> bool;` 415 | 416 | La funzione applicata ad un numero intero ritorna true se il numero appartiene all'insieme, false altrimenti. L'insieme vuoto è quindi rappresentato da una funzione che ritorna sempre false: 417 | 418 | `val vuoto:insiemediinteri = fn n => false;` 419 | 420 | ed un intero può essere aggiunto ad un insieme tramite la funzione aggiungi: 421 | 422 | ``` 423 | val aggiungi = fn f:insiemediinteri => fn x:int => (fn n:int => if (n = x) 424 | then true 425 | else false):insiemediinteri; 426 | ``` 427 | 428 | É possibile verificare se un intero è contenuto in un insieme tramite la funzione contiene: 429 | 430 | `val contiene = fn f:insiemediinteri => fn n:int => f n;` 431 | 432 | Si implementi la funzione **unione**, avente tipo `insiemediinteri -> insiemediinteri -> insiemediinteri` che dati due insiemi di interi ne calcola l’unione. 433 | 434 | ##### Soluzione 435 | 436 | ``` 437 | val unione = fn i1:insiemediinteri => fn i2:insiemediinteri => (fn n => ((contiene i1 n) orelse (contiene i2 n))):insiemediinteri; 438 | ``` 439 | 440 | ### Esame giugno 2017 441 | 442 | #### Turno 1 G2017 443 | 444 | ##### Testo 445 | 446 | Si scriva una funzione **sommali** (avente tipo `int -> int list -> int`) che riceve come argomento un intero n ed una lista di interi l. La funzione **sommali** somma ad n gli elementi di l che hanno posizione pari (se la lista contiene meno di 2 elementi, sommali ritorna n). 447 | 448 | Come esempio, l'invocazione 449 | `sommali 0 [1,2];` 450 | deve avere risultato 2; 451 | `sommali 1 [1,2,3];` 452 | deve avere risultato 3; 453 | `sommali 2 [1,2,3,4];` 454 | deve avere risultato 8. 455 | 456 | ##### Soluzione 457 | 458 | ``` 459 | fun sommali z [] = z 460 | | sommali z (a::[]) = z 461 | | sommali z (a::b::c) = b + (sommali z c); 462 | ``` 463 | 464 | altro modo extra usando fn -> stesso risultato 465 | 466 | ``` 467 | val rec sommali_diversa = fn z => fn [] => z 468 | | a::[] => z 469 | | a::b::c => b + (sommali z c); 470 | ``` 471 | 472 | ##### Testing (Non fa parte della soluzione - utile per capire) 473 | 474 | ``` 475 | sommali 0 [1,2]; 476 | sommali 1 [1,2,3]; 477 | sommali 2 [1,2,3,4]; 478 | 479 | sommali_diversa 0 [1,2]; 480 | sommali_diversa 1 [1,2,3]; 481 | sommali_diversa 2 [1,2,3,4]; 482 | ``` 483 | 484 | #### Turno 2 G2017 485 | 486 | ##### Testo 487 | 488 | Si scriva una funzione **sommali** (avente tipo `int -> int list -> int`) che riceve come argomento un intero n ed una lista di interi l. La funzione **sommali** somma ad n gli elementi di l che hanno posizione multipla di 3 (se la lista contiene meno di 3 elementi, sommali ritorna n). 489 | 490 | Come esempio, l'invocazione 491 | `sommali 0 [1,2,3];` 492 | deve avere risultato 3, 493 | `sommali 1 [1,2,3];` 494 | deve avere risultato 4: e 495 | `sommali 2 [1,2,3,4,5,6];` 496 | deve avere risultato 11. 497 | 498 | ##### Soluzione 499 | 500 | ``` 501 | fun sommali z [] = z 502 | | sommali z (a::[]) = z 503 | | sommali z (a::b::[]) = z 504 | | sommali z (a::b::c::d) = c + (sommali z d); 505 | ``` 506 | 507 | altro modo extra usando fn -> stesso risultato 508 | 509 | ``` 510 | val rec sommali_diversa = fn z => fn [] => z 511 | | a::[] => z 512 | | a::b::[] => z 513 | | a::b::c::d => c + (sommali z d); 514 | ``` 515 | 516 | ##### Testing (Non fa parte della soluzione - utile per capire) 517 | 518 | ``` 519 | sommali 0 [1,2,3]; 520 | sommali 1 [1,2,3]; 521 | sommali 2 [1,2,3,4,5,6]; 522 | 523 | sommali_diversa 0 [1,2,3]; 524 | sommali_diversa 1 [1,2,3]; 525 | sommali_diversa 2 [1,2,3,4,5,6]; 526 | ``` 527 | 528 | ### Esame luglio 2017 529 | 530 | #### Turno 1 L2017 531 | 532 | ##### Testo 533 | 534 | Si consideri il tipo di dato `FOR = For of int * (int -> int);` i cui valori `For(n, f)` rappresentano funzioni che implementano un ciclo for come il seguente: 535 | 536 | ``` 537 | int ciclofor (int x) { 538 | for (int i = 0; i < n; i++) { 539 | x = f(x); 540 | } 541 | } 542 | ``` 543 | 544 | Si scriva una funzione **eval** (avente tipo `FOR -> (int -> int)`) che riceve come argomento un valore di tipo FOR e ritorna una funzione da interi ad interi che implementa il ciclo indicato qui sopra (applica n - 1 volte la funzione f all'argomento). 545 | 546 | Come esempio, `se val f = fn x => x * 2`, allora eval `(For(3, f))` ritornerà una funzione che dato un numero i ritorna i = 8: 547 | 548 | **Esempi esecuzione:** 549 | 550 | > val f = fn x => x \* 2; 551 | > `val f = fn: int -> int` 552 | > eval (For(3, f)); 553 | > `val it = fn: int -> int` 554 | > val g = eval (For(3, f)); 555 | > `val g = fn: int -> int` 556 | > g 5; 557 | > `val it = 40: int` 558 | 559 | ##### Soluzione 560 | 561 | ``` 562 | datatype FOR = For of int * (int -> int); 563 | val rec eval = fn For (n, f) => fn x => if (n > 0) 564 | then 565 | eval (For (n - 1, f)) (f x) 566 | else 567 | x; 568 | ``` 569 | 570 | ##### Testing (Non fa parte della soluzione - utile per capire) 571 | 572 | ``` 573 | val f = fn x => x * 2; 574 | eval (For(3, f)); 575 | val g = eval (For(3, f)); 576 | g 5; 577 | ``` 578 | 579 | #### Turno 2 L2017 580 | 581 | ##### Testo 582 | 583 | Si consideri il tipo di dato `FOR = For of int * (int -> int);` i cui valori `For(n, f)` rappresentano funzioni che implementano un ciclo for come il seguente: 584 | 585 | ``` 586 | int ciclofor (int x) { 587 | for (int i = 1; i < n; i++) { 588 | x = f(x); 589 | } 590 | } 591 | ``` 592 | 593 | Si scriva una funzione **eval** (avente tipo `FOR -> (int -> int)`) che riceve come argomento un valore di tipo FOR e ritorna una funzione da interi ad interi che implementa il ciclo indicato qui sopra (applica n - 1 volte la funzione f all'argomento). 594 | 595 | Come esempio, se `val f = fn x => x * 2` allora eval `(For(3, f))` ritornerà una funzione che dato un numero i ritorna i = 4: 596 | 597 | **Esempi esecuzione:** 598 | 599 | > val f = fn x => x \* 2; 600 | > `val f = fn: int -> int` 601 | > eval (For(3, f)); 602 | > `val it = fn: int -> int` 603 | > val g = eval (For(3, f)); 604 | > `val g = fn: int -> int` 605 | > g 5; 606 | > `val it = 20: int` 607 | 608 | ##### Soluzione 609 | 610 | ``` 611 | datatype FOR = For of int * (int -> int); 612 | val rec eval = fn For (n, f) => fn x => if (n > 1) 613 | then 614 | eval (For (n - 1, f)) (f x) 615 | else 616 | x; 617 | ``` 618 | 619 | ##### Testing (Non fa parte della soluzione - utile per capire) 620 | 621 | ``` 622 | val f = fn x => x * 2; 623 | eval (For(3, f)); 624 | val g = eval (For(3, f)); 625 | g 5; 626 | ``` 627 | 628 | ### Esame settembre 2017 629 | 630 | ##### Testo 631 | 632 | Si consideri il tipo di dato 633 | 634 | `datatype intonil = Nil | Int of int;` 635 | 636 | ed una possibile implementazione semplificata di ambiente (che considera solo valori interi) basata su di esso: 637 | 638 | `type ambiente = string -> intonil` 639 | 640 | In questa implementazione, un ambiente è rappresentato da una funzione che mappa nomi (valori di tipo string) in valori di tipo intonil (che rappresentano un intero o nessun valore). Tale funzione applicata ad un nome ritorna il valore intero ad esso associato oppure Nil. Usando questa convenzione, l'ambiente vuoto (in cui nessun nome è associato a valori) può essere definito come: 641 | 642 | `val ambientevuoto = fn _:string => Nil;` 643 | 644 | Basandosi su queste definizioni, si definisca una funzione **lega** con `tipo ambiente -> string -> int -> ambiente`. che a partire da un ambiente (primo argomento) genera un nuovo ambiente (valore di ritorno) uguale al primo argomento più un legame fra il nome e l'intero ricevuti come secondo e terzo argomento. 645 | 646 | Esempio: 647 | – `((lega ambientevuoto "a"1)"a")` deve ritornare Int 1; 648 | – `((lega ambientevuoto "a"1)"boh")` deve ritornare Nil; 649 | – `((lega (lega ambientevuoto "a"1)"boh"~1)"boh")` deve ritornare Int ~1; 650 | – `((lega (lega ambientevuoto "a"1)"boh"~1)"mah")` deve ritornare Nil. 651 | 652 | ##### Soluzione 653 | 654 | ``` 655 | val lega = fn e:ambiente => fn nome => fn valore => (fn n => if (n = nome) 656 | then 657 | (Int valore) 658 | else 659 | (e n)):ambiente; 660 | ``` 661 | 662 | ##### Testing (Non fa parte della soluzione - utile per capire) 663 | 664 | ``` 665 | ((lega ambientevuoto "a"1)"a"); 666 | ((lega ambientevuoto "a"1)"boh"); 667 | ((lega (lega ambientevuoto "a"1)"boh"~1)"boh"); 668 | ((lega (lega ambientevuoto "a"1)"boh"~1)"mah"); 669 | ``` 670 | 671 | ### Esame gennaio 2018 672 | 673 | ##### Testo 674 | 675 | Si consideri il tipo di dato: 676 | 677 | ``` 678 | datatype lambda_expr = Var of string 679 | | Lambda of string * lambda_expr 680 | | Apply of lambda_expr * lambda_expr; 681 | ``` 682 | 683 | che rappresenta un'espressione del Lambda-calcolo. 684 | Il costruttore Var crea un'espressione costituita da un'unica funzione / variabile (il cui nome è un valore di tipo string); Il costruttore Lambda crea una Lambda-espressione a partire da un'altra espressione, legandone una variabile (indicata da un valore di tipo string); 685 | Il costruttore Apply crea un'espressione data dall'applicazione di un'espressione ad un'altra. 686 | 687 | Si scriva una funzione **is_bound** (avente tipo `string -> lambda_expr -> bool`) che riceve come argomenti una stringa (che rappresenta il nome di una variabile / funzione) ed una Lambda-espressione, ritornando true se la variabile indicata appare come legata nell'espressione, false altrimenti. 688 | 689 | ##### Soluzione 690 | 691 | ``` 692 | val rec is_bound = fn s => fn Var v => s = v 693 | | Lambda (v, e) => if (s = v) then true else is_bound s e 694 | | Apply (e1, e2) => (is_bound s e1) orelse (is_bound s e2); 695 | ``` 696 | 697 | ##### Testing (Non fa parte della soluzione - utile per capire) 698 | 699 | ``` 700 | is_bound "a" (Var "a"); 701 | is_bound "b" (Var "a"); 702 | is_bound "a" (Lambda ("a", Apply((Var "a"), Var "b"))); 703 | is_bound "b" (Lambda ("a", Apply((Var "a"), Var "b"))); 704 | ``` 705 | 706 | ### Esame giugno 2018 707 | 708 | ##### Testo 709 | 710 | Si scriva una funzione **conta** (avente tipo `''a list -> int`) che riceve come argomento una lista di ''a l. La funzione **conta** ritorna il numero di elementi della lista senza considerare i duplicati. 711 | 712 | ##### Soluzione 713 | 714 | ``` 715 | val rec conta = fn [] => 0 716 | | a::b => if (List.exists ((fn y => a = y)) b) 717 | then 718 | (conta b) 719 | else 720 | 1+(conta b); 721 | ``` 722 | 723 | ##### Testing (Non fa parte della soluzione - utile per capire) 724 | 725 | ``` 726 | conta ["pera", "pera", "pera", "pera"]; 727 | conta ["red", "red", "green", "blue"]; 728 | conta ["red"]; 729 | conta []; 730 | conta [1,2,4,5,6,0,1,4,5]; 731 | conta [true, false, true, false]; 732 | conta [#"A",#"a",#"B",#"b"]; 733 | ``` 734 | 735 | ### Esame luglio 2018 736 | 737 | ##### Testo 738 | 739 | Si consideri il tipo di dato `ITER = Iter of int * (int -> int);` i cui valori `ITER(n, f)` rappresentano funzioni che implementano un ciclo for come il seguente: 740 | 741 | ``` 742 | int ITER (int x) { 743 | for (int i = 1; i < n; i++) { 744 | x = f(x); 745 | } 746 | } 747 | ``` 748 | 749 | Si scriva una funzione eval (avente tipo `Iter -> (int -> int)`) che riceve come argomento un valore di tipo Iter e ritorna una funzione da interi ad interi che implementa il ciclo indicato qui sopra (applica n - 1 volte la funzione f all'argomento). 750 | 751 | Come esempio, se val `f = fn x => x * 2`, allora eval `(Iter(3, f))` ritornerà una funzione che dato un numero i ritorna i = 8: 752 | 753 | ESEMPI ESECUZIONE: 754 | 755 | > val f = fn x => x \* 2; 756 | > `val f = fn: int -> int` 757 | > eval (Iter(3, f)); 758 | > `val it = fn: int -> int` 759 | > val g = eval (Iter(3, f)); 760 | > `val g = fn: int -> int` 761 | > g 5; 762 | > `val it = 40: int` 763 | 764 | ##### Soluzione 765 | 766 | ``` 767 | datatype ITER = Iter of int * (int -> int); 768 | val rec eval = fn Iter (n, f) => fn x => if (n > 0) then eval (Iter (n-1, f)) (f x) else x; 769 | ``` 770 | 771 | ##### Testing (Non fa parte della soluzione - utile per capire) 772 | 773 | ``` 774 | val f = fn x => x * 2; 775 | eval (Iter(3, f)); 776 | val g = eval (Iter(3, f)); 777 | g 5; 778 | ``` 779 | 780 | ### Esame agosto 2018 781 | 782 | ##### Testo 783 | 784 | Scrivere una funzione **prod** che calcoli il prodotto di tutti gli interi tra 2 numeri m ed n. (con m >= m inclusi). 785 | 786 | Usare poi questa funzione per scrivere una funzione Comb(n,k) la quale calcola il numero di combinazioni di n elementi presi k a k. 787 | Definita dalla formula matematica: `C(n, k) = n!/(k! \* (n − k)!)` 788 | che equivale anche a: `C(n, k) = (n − k + 1) · (n − k + 2)· · · n/1 · 2 · · · k` 789 | 790 | ##### Soluzione 791 | 792 | ``` 793 | fun prod(m, n) = if (n <= m) then m else n * prod(m, n-1); 794 | 795 | fun comb(n, k) = (prod(n-k+1, n)) div (prod(1, k)); 796 | ``` 797 | 798 | ##### Testing (Non fa parte della soluzione - utile per capire) 799 | 800 | ``` 801 | comb(5,3); 802 | comb(7,5); 803 | comb(9,1); 804 | ``` 805 | 806 | ### Esame giugno 2019 807 | 808 | ##### Testo 809 | 810 | Scrivere una funzione **f** di tipo `int list -> int list` che presa in input una lista trasformi ogni elemento "a" della lista nel seguente modo: 811 | 812 | - se a >= 0 allora l'elemento "a" dovrà essere trasformato in a2-1 813 | - altrimenti l'elemento "a" dovrà essere trasformato in a2+1 814 | 815 | ESEMPIO 816 | `f [~1,2,3,0,~5,6];` 817 | dovrà dare in output: 818 | `val it = [2, 3, 8, ~1, 26, 35]: int list` 819 | 820 | ##### Soluzione 821 | 822 | ``` 823 | fun f [] = [] 824 | | f (a::b) = if (a>=0) then ((a*a)-1)::(f b) else ((a*a)+1)::(f b); 825 | ``` 826 | 827 | ##### Testing (Non fa parte della soluzione - utile per capire) 828 | 829 | ``` 830 | f [~1,2,3,0,~5,6]; 831 | f [0,~1]; 832 | ``` 833 | 834 | ### Esame luglio 2019 835 | 836 | > L'esame era molto simile a quello di giugno dovrebbe essere cambiata solo l'operazione da svolgere sugli elementi. 837 | > Sfortunatamente non sono riuscito a reperire il testo :( 838 | 839 | ### Esame settembre 2019 840 | 841 | ##### Testo 842 | 843 | Scrivere una funzione chiamata **f** che prende in input un file "text.txt" la funzione deve ritornare la lista dei caratteri senza spazi presenti nel file di testo. 844 | 845 | Si assuma che il file sia presente nella stessa cartella. 846 | 847 | Esempio: 848 | Dato il file "text.txt" che contiene: 849 | ab e ad c 850 | Eseguendo il comando `use "esercizio.sml"`; 851 | dovrà essere prodotto il seguente risultato: 852 | `val it = [#"a", #"b", #"e", #"a", #"d", #"c"]: char list` 853 | 854 | ##### Soluzione 855 | 856 | ``` 857 | fun f filename = 858 | let 859 | val file = TextIO.openIn filename 860 | val str = TextIO.inputAll file 861 | in 862 | TextIO.closeIn file; 863 | List.filter (fn c => c <> #" " andalso c <> #"\t" andalso c <> #"\n") (explode str) 864 | end; 865 | f "text.txt"; 866 | ``` 867 | 868 | ### Esame gennaio 2020 869 | 870 | ##### Testo 871 | 872 | Scrivere una funzione chiamata **f** che prende in input un file "text2.txt" la funzione deve ritornare i caratteri in posizione pari presenti nel file txt. Il file txt conterrà un numero di caratteri pari maggiore di zero. 873 | 874 | Si assuma che il file sia presente nella stessa cartella. 875 | 876 | ESEMPIO di esecuzione 877 | Dato il file "text2.txt" che contiene: 878 | abcdef 879 | Eseguendo il comando `use "esercizio.sml";` 880 | dovrà essere prodotto il seguente risultato: 881 | `val it = ["b","d","f"]: string list` 882 | 883 | ##### Soluzione 884 | 885 | ``` 886 | fun f filename = 887 | let 888 | val file = TextIO.openIn filename 889 | val str = TextIO.inputAll file 890 | val rec elem_pari = fn [] => [] 891 | | a::[] => [] 892 | | a::b::c => Char.toString(b)::(elem_pari c) 893 | in 894 | TextIO.closeIn file; 895 | elem_pari (explode str) 896 | end; 897 | f "text2.txt"; 898 | ``` 899 | 900 | ### Esame febbraio 2020 901 | 902 | ##### Testo 903 | 904 | Scrivere una funzione **f** che data una lista di interi restituisca true se essa è ordinata in ordine crescente false altrimenti 905 | 906 | ##### Soluzione 907 | 908 | ``` 909 | fun f [] = true 910 | | f (a::[]) = true 911 | | f (a::b::l) = if a > b then false else f(b::l); 912 | ``` 913 | 914 | Oppure altra **soluzione valida** - presa dalle slide 915 | 916 | ``` 917 | val rec f1 = fn l => 918 | if List.null l then true 919 | else if List.null (tl l) then true 920 | else (hd l <= hd (tl l)) andalso f1 (tl l); 921 | ``` 922 | 923 | ##### Testing (Non fa parte della soluzione - utile per capire) 924 | 925 | ``` 926 | f [1,2,2,3,4]; 927 | f[3,2,1]; 928 | f[4,12,3,44,0]; 929 | 930 | f1 [1,2,2,3,4]; 931 | f1[3,2,1]; 932 | f1[4,12,3,44,0]; 933 | ``` 934 | 935 | ### Esame giugno 2020 936 | 937 | #### Turno 1 G2020 938 | 939 | ##### Testo 940 | 941 | Si scriva una funzione **sommali** (avente tipo `int -> int list -> int`) che riceve come argomento un intero `n` ed una lista di interi `l`. 942 | La funzione **sommali** somma ad n gli elementi di l che hanno posizione pari (se la lista contiene meno di 2 elementi, sommali ritorna n). 943 | 944 | Come esempio, l'invocazione 945 | 946 | ``` 947 | sommali 0 [1,2]; 948 | deve avere risultato 2, 949 | sommali 1 [1,2,3]; 950 | deve avere risultato 3: e 951 | sommali 2 [1,2,3,4]; 952 | deve avere risultato 8. 953 | ``` 954 | 955 | IMPORTANTE: notare il tipo della funzione!. 956 | 957 | La funzione sommali deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. Si consegni il file .sml contenente la definizione di sommali. 958 | 959 | ##### Soluzione 960 | 961 | ``` 962 | fun sommali z [] = z 963 | | sommali z (a::[]) = z 964 | | sommali z (a::b::c) = b + (sommali z c); 965 | ``` 966 | 967 | ##### Testing (Non fa parte della soluzione - utile per capire) 968 | 969 | ``` 970 | sommali 0 [1,2]; 971 | sommali 1 [1,2,3]; 972 | sommali 2 [1,2,3,4]; 973 | ``` 974 | 975 | #### Turno 2 G2020 976 | 977 | ##### Testo 978 | 979 | Si scriva una funzione **conta** (avente tipo `''a list -> int`) che riceve come argomento una lista di `''a l`. La funzione **conta** ritorna il numero di elementi della lista senza considerare i duplicati. 980 | 981 | Come esempio, l'invocazione 982 | 983 | ``` 984 | conta ["pera", "pera", "pera", "pera"]; deve avere risultato 1; 985 | conta ["red", "red", "green", "blue"]; deve avere risultato 3. 986 | ``` 987 | 988 | La funzione conta deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. Si consegni il file .sml contenente la definizione di conta. 989 | 990 | ##### Soluzione 991 | 992 | ``` 993 | val rec conta = fn [] => 0 994 | | a::b => if (List.exists ((fn y => a = y)) b) then (conta b) else 1+(conta b); 995 | ``` 996 | 997 | ##### Testing (Non fa parte della soluzione - utile per capire) 998 | 999 | ``` 1000 | conta ["pera", "pera", "pera", "pera"]; 1001 | conta ["red", "red", "green", "blue"]; 1002 | conta ["red"]; 1003 | conta []; 1004 | conta [1,2,4,5,6,0,1,4,5]; 1005 | conta [true, false, true, false]; 1006 | conta [#"A",#"a",#"B",#"b"]; 1007 | ``` 1008 | 1009 | ### Esame luglio 2020 1010 | 1011 | ##### Testo 1012 | 1013 | Si consideri il tipo di dato 1014 | 1015 | `datatype intonil = Nil | Int of int;` 1016 | 1017 | ed una possibile implementazione semplificata di ambiente (che considera solo valori interi) basata su di esso: 1018 | 1019 | `type ambiente = string -> intonil` 1020 | 1021 | In questa implementazione, un ambiente è rappresentato da una funzione che mappa nomi (valori di tipo string) in valori di tipo intonil (che rappresentano un intero o nessun valore). Tale funzione applicata ad un nome ritorna il valore intero ad esso associato oppure Nil. Usando questa convenzione, l'ambiente vuoto (in cui nessun nome è associato a valori) può essere definito come: 1022 | 1023 | `val ambientevuoto = fn _:string => Nil;` 1024 | 1025 | Basandosi su queste definizioni, si definisca una funzione **lega** con `tipo ambiente -> string -> int -> ambiente`. che a partire da un ambiente (primo argomento) genera un nuovo ambiente (valore di ritorno) uguale al primo argomento più un legame fra il nome e l'intero ricevuti come secondo e terzo argomento. 1026 | 1027 | Esempio: 1028 | – `((lega ambientevuoto "a"1)"a")` deve ritornare Int 1; 1029 | – `((lega ambientevuoto "a"1)"boh")` deve ritornare Nil; 1030 | – `((lega (lega ambientevuoto "a"1)"boh"~1)"boh")` deve ritornare Int ~1; 1031 | – `((lega (lega ambientevuoto "a"1)"boh"~1)"mah")` deve ritornare Nil. 1032 | 1033 | La funzione lega deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. Non è necessario che contenga la definizione del tipo di dato intonil, di ambiente o del valore ambientevuoto. Si consegni il file .sml contenente la definizione di lega utilizzando il form qui sotto riportato. 1034 | 1035 | ##### Soluzione 1036 | 1037 | ``` 1038 | val lega = fn e:ambiente => fn nome => fn valore => (fn n => if (n = nome) 1039 | then 1040 | (Int valore) 1041 | else 1042 | (e n)):ambiente; 1043 | ``` 1044 | 1045 | ##### Testing (Non fa parte della soluzione - utile per capire) 1046 | 1047 | ``` 1048 | ((lega ambientevuoto "a"1)"a"); 1049 | ((lega ambientevuoto "a"1)"boh"); 1050 | ((lega (lega ambientevuoto "a"1)"boh"~1)"boh"); 1051 | ((lega (lega ambientevuoto "a"1)"boh"~1)"mah"); 1052 | ``` 1053 | 1054 | ### Esame settembre 2020 1055 | 1056 | ##### Testo 1057 | 1058 | Si consideri il tipo di dato `FOR = For of int * (int -> int);` i cui valori `For(n, f)` rappresentano funzioni che implementano un ciclo for come il seguente: 1059 | 1060 | ``` 1061 | int ciclofor (int x) { 1062 | for (int i = 0; i < n; i++) { 1063 | x = f(x); 1064 | } 1065 | return x; 1066 | } 1067 | ``` 1068 | 1069 | Si scriva una funzione **eval** (avente tipo `FOR -> (int -> int)`) che riceve come argomento un valore di tipo FOR e ritorna una funzione da interi ad interi che implementa il ciclo indicato qui sopra (applica n volte la funzione f all'argomento). 1070 | 1071 | Come esempio, `se val f = fn x => x * 2`, allora eval `(For(3, f))` ritornerà una funzione che dato un numero i ritorna i \* 8: 1072 | 1073 | **Esempi esecuzione:** 1074 | 1075 | > val f = fn x => x \* 2; 1076 | > `val f = fn: int -> int` 1077 | > eval (For(3, f)); 1078 | > `val it = fn: int -> int` 1079 | > val g = eval (For(3, f)); 1080 | > `val g = fn: int -> int` 1081 | > g 5; 1082 | > `val it = 40: int` 1083 | 1084 | ##### Soluzione 1085 | 1086 | ``` 1087 | datatype FOR = For of int * (int -> int); 1088 | val rec eval = fn For (n, f) => fn x => if (n > 0) 1089 | then 1090 | eval (For (n - 1, f)) (f x) 1091 | else 1092 | x; 1093 | ``` 1094 | 1095 | ##### Testing (Non fa parte della soluzione - utile per capire) 1096 | 1097 | ``` 1098 | val f = fn x => x * 2; 1099 | eval (For(3, f)); 1100 | val g = eval (For(3, f)); 1101 | g 5; 1102 | ``` 1103 | 1104 | ### Esame febbraio 2021 1105 | 1106 | ##### Testo 1107 | 1108 | Implementare una funzione **f** che data una lista `[a1,...,an]`, calcoli `a1-a2+a3-a4+...` 1109 | La funzione così definita dovrà funzionare con liste di **qualsiasi lunghezza**. 1110 | 1111 | ##### Soluzione 1112 | 1113 | ``` 1114 | fun f [] = 0 1115 | | f (a::[]) = a 1116 | | f (a::b::[]) = a - b 1117 | | f (a::b::l) = a - b + f(l); 1118 | ``` 1119 | 1120 | ##### Testing (Non fa parte della soluzione - utile per capire) 1121 | 1122 | ``` 1123 | f []; 1124 | f [1]; 1125 | f [1,2]; 1126 | f [1,2,3]; 1127 | f [1,2,3,4]; 1128 | f [3,3,3,3,3,3,3,3,3,3,3,3]; 1129 | f [3,3,3,3,3,3,3,3,3,3,3,3,3]; 1130 | ``` 1131 | 1132 | ### Esame giugno 2021 1133 | 1134 | ##### Testo 1135 | 1136 | Implementare una funzione **f** che, dato un file `"text.txt"` contenente una lista con un numero 1137 | pari di caratteri restituisca una lista (type `string list`) di coppie di caratteri, ignorando i 1138 | primi due e proponendo i successivi due iterativamente (quindi si avranno i caratteri 3,4 seguiti 1139 | da 7,8, e così via). 1140 | 1141 | Il file contenente il codice e file `"text.txt"` devono trovarsi nella stessa directory. Il file 1142 | `"text.txt"` di esempio viene fornito unitamente a questo file. 1143 | 1144 | Un'ipotetica esecuzione del codice da bash potrebbe essere: 1145 | 1146 | Assicurarsi di avere il file `"text.txt"`. 1147 | Lanciare poly da terminale 1148 | 1149 | > use "cognome_nome.sml"; 1150 | val it = ["ac","ef","54",""]: string list 1151 | 1152 | La funzione **f** deve essere definita in un file `.sml` autocontenuto ma separato da qualsiasi codice 1153 | di test sia usato. Si consegni il file `.sml` contente la definizione di **f**. Rinominare il file con 1154 | `cognome_nome.sml`. 1155 | 1156 | ##### Soluzione 1157 | 1158 | ``` 1159 | fun f filename = 1160 | let 1161 | val file = TextIO.openIn(filename); 1162 | val lista = explode (TextIO.inputAll file); 1163 | fun coppie nil = [""] 1164 | | coppie [_] = [""] 1165 | | coppie (a::b::[]) = [""] 1166 | | coppie (a::b::c::[]) = [""] 1167 | | coppie (a::b::c::d::[]) = implode [c, d] :: [""] 1168 | | coppie (a::b::c::d::l) = (implode [c, d]) :: coppie l; 1169 | in 1170 | TextIO.closeIn file; 1171 | coppie lista 1172 | end; 1173 | f "text.txt"; 1174 | 1175 | ``` 1176 | Oppure altra **soluzione valida** *(By Alessio Blascovich)* 1177 | 1178 | ``` 1179 | val input = TextIO.openIn("text.txt"); 1180 | fun f file=if TextIO.endOfStream(file) then [TextIO.inputN(file,2)] else 1181 | let 1182 | val trash=TextIO.inputN(file,2) 1183 | val keep=TextIO.inputN(file,2) 1184 | in 1185 | keep::(f file) 1186 | end; 1187 | f input; 1188 | ``` 1189 | 1190 | ### Esame luglio 2021 1191 | 1192 | ##### Testo 1193 | 1194 | Si scriva una funzione **conta** (avente tipo `' 'a list -> int`) che riceve come argomento una lista di `' 'a`. La funzione conta ritorna il numero di elementi della lista senza considerare i duplicati. 1195 | 1196 | Come esempio, l'invocazione `conta ["pera", "pera", "pera", "pera"];` deve avere risultato 1, conta `["red", "red", "green", "blue"];` deve avere risultato **3** e `conta [2, 3, 4, 2];` deve avere risultato **3**. 1197 | 1198 | **IMPORTANTE**: notare il tipo della funzione! 1199 | 1200 | ##### Soluzione 1201 | 1202 | ``` 1203 | val rec conta = fn [] => 0 1204 | | a::b => if (List.exists ((fn y => a = y)) b) then (conta b) else 1+(conta b); 1205 | ``` 1206 | 1207 | ##### Testing (Non fa parte della soluzione - utile per capire) 1208 | 1209 | ``` 1210 | conta ["pera", "pera", "pera", "pera"]; 1211 | conta ["red", "red", "green", "blue"]; 1212 | conta ["red"]; 1213 | conta []; 1214 | conta [1,2,4,5,6,0,1,4,5]; 1215 | conta [true, false, true, false]; 1216 | conta [#"A",#"a",#"B",#"b"]; 1217 | ``` 1218 | 1219 | ### Esame gennaio 2022 1220 | 1221 | ##### Testo 1222 | 1223 | Si scriva una funzione **sommali** (avente tipo `int -> int list -> int`) che riceve come argomento un intero n ed una lista di interi l. La funzione **sommali** somma ad n gli elementi di l che hanno posizione pari (se la lista contiene meno di 2 elementi, sommali ritorna n). 1224 | 1225 | Come esempio, l'invocazione 1226 | `sommali 0 [1,2];` 1227 | deve avere risultato 2; 1228 | `sommali 1 [1,2,3];` 1229 | deve avere risultato 3; 1230 | `sommali 2 [1,2,3,4];` 1231 | deve avere risultato 8. 1232 | 1233 | ##### Soluzione 1234 | 1235 | ``` 1236 | fun sommali z [] = z 1237 | | sommali z (a::[]) = z 1238 | | sommali z (a::b::c) = b + (sommali z c); 1239 | ``` 1240 | 1241 | altro modo extra usando fn -> stesso risultato 1242 | 1243 | ``` 1244 | val rec sommali_diversa = fn z => fn [] => z 1245 | | a::[] => z 1246 | | a::b::c => b + (sommali z c); 1247 | ``` 1248 | 1249 | ##### Testing (Non fa parte della soluzione - utile per capire) 1250 | 1251 | ``` 1252 | sommali 0 [1,2]; 1253 | sommali 1 [1,2,3]; 1254 | sommali 2 [1,2,3,4]; 1255 | 1256 | sommali_diversa 0 [1,2]; 1257 | sommali_diversa 1 [1,2,3]; 1258 | sommali_diversa 2 [1,2,3,4]; 1259 | ``` 1260 | 1261 | ### Esame giugno 2022 1262 | 1263 | ##### Testo 1264 | 1265 | Implementare una funzione **f** che, dato un file `"text.txt"` contenente una lista con un numero 1266 | pari di caratteri restituisca una lista (type `string list`) di coppie di caratteri, ignorando i 1267 | primi due e proponendo i successivi due iterativamente (quindi si avranno i caratteri 3,4 seguiti 1268 | da 7,8, e così via). 1269 | 1270 | Il file contenente il codice e file `"text.txt"` devono trovarsi nella stessa directory. Il file 1271 | `"text.txt"` di esempio viene fornito unitamente a questo file. 1272 | 1273 | Un'ipotetica esecuzione del codice da bash potrebbe essere: 1274 | 1275 | Assicurarsi di avere il file `"text.txt"`. 1276 | Lanciare poly da terminale 1277 | 1278 | > use "cognome_nome.sml"; 1279 | val it = ["ac","ef","54",""]: string list 1280 | 1281 | La funzione **f** deve essere definita in un file `.sml` autocontenuto ma separato da qualsiasi codice 1282 | di test sia usato. Si consegni il file `.sml` contente la definizione di **f**. Rinominare il file con 1283 | `cognome_nome.sml`. 1284 | 1285 | ##### Soluzione 1286 | 1287 | ``` 1288 | fun f filename = 1289 | let 1290 | val file = TextIO.openIn(filename); 1291 | val lista = explode (TextIO.inputAll file); 1292 | fun coppie nil = [""] 1293 | | coppie [_] = [""] 1294 | | coppie (a::b::[]) = [""] 1295 | | coppie (a::b::c::[]) = [""] 1296 | | coppie (a::b::c::d::[]) = implode [c, d] :: [""] 1297 | | coppie (a::b::c::d::l) = (implode [c, d]) :: coppie l; 1298 | in 1299 | TextIO.closeIn file; 1300 | coppie lista 1301 | end; 1302 | f "text.txt"; 1303 | 1304 | ``` 1305 | Oppure altra **soluzione valida** *(By Alessio Blascovich)* 1306 | 1307 | ``` 1308 | val input = TextIO.openIn("text.txt"); 1309 | fun f file=if TextIO.endOfStream(file) then [TextIO.inputN(file,2)] else 1310 | let 1311 | val trash=TextIO.inputN(file,2) 1312 | val keep=TextIO.inputN(file,2) 1313 | in 1314 | keep::(f file) 1315 | end; 1316 | f input; 1317 | ``` 1318 | 1319 | ### Esame luglio 2022 1320 | 1321 | ##### Testo 1322 | 1323 | Scrivere una funzione **f** di tipo `int list -> int list` che presa in input una lista trasformi ogni elemento "a" della lista nel seguente modo: 1324 | 1325 | - se a >= 0 allora l'elemento "a" dovrà essere trasformato in a2-1 1326 | - altrimenti l'elemento "a" dovrà essere trasformato in a2+1 1327 | 1328 | ESEMPIO 1329 | `f [~1,2,3,0,~5,6];` 1330 | dovrà dare in output: 1331 | `val it = [2, 3, 8, ~1, 26, 35]: int list` 1332 | 1333 | ##### Soluzione 1334 | 1335 | ``` 1336 | fun f [] = [] 1337 | | f (a::b) = if (a>=0) then ((a*a)-1)::(f b) else ((a*a)+1)::(f b); 1338 | ``` 1339 | 1340 | ##### Testing (Non fa parte della soluzione - utile per capire) 1341 | 1342 | ``` 1343 | f [~1,2,3,0,~5,6]; 1344 | f [0,~1]; 1345 | ``` 1346 | 1347 | ### Esame febbraio 2023 1348 | 1349 | ##### Testo 1350 | 1351 | Si consideri il tipo di dato 1352 | 1353 | `datatype intonil = Nil | Int of int;` 1354 | 1355 | ed una possibile implementazione semplificata di ambiente (che considera solo valori interi) basata su di esso: 1356 | 1357 | `type ambiente = string -> intonil` 1358 | 1359 | In questa implementazione, un ambiente è rappresentato da una funzione che mappa nomi (valori di tipo string) in valori di tipo intonil (che rappresentano un intero o nessun valore). Tale funzione applicata ad un nome ritorna il valore intero ad esso associato oppure Nil. Usando questa convenzione, l'ambiente vuoto (in cui nessun nome è associato a valori) può essere definito come: 1360 | 1361 | `val ambientevuoto = fn _:string => Nil;` 1362 | 1363 | Basandosi su queste definizioni, si definisca una funzione **lega** con `tipo ambiente -> string -> int -> ambiente`. che a partire da un ambiente (primo argomento) genera un nuovo ambiente (valore di ritorno) uguale al primo argomento più un legame fra il nome e l'intero ricevuti come secondo e terzo argomento. 1364 | 1365 | Esempio: 1366 | – `((lega ambientevuoto "a"1)"a")` deve ritornare Int 1; 1367 | – `((lega ambientevuoto "a"1)"boh")` deve ritornare Nil; 1368 | – `((lega (lega ambientevuoto "a"1)"boh"~1)"boh")` deve ritornare Int ~1; 1369 | – `((lega (lega ambientevuoto "a"1)"boh"~1)"mah")` deve ritornare Nil. 1370 | 1371 | La funzione lega deve essere definita in un file .sml autocontenuto ma separato da qualsiasi codice di test si sia usato. Non è necessario che contenga la definizione del tipo di dato intonil, di ambiente o del valore ambientevuoto. Si consegni il file .sml contenente la definizione di lega utilizzando il form qui sotto riportato. 1372 | 1373 | ##### Soluzione 1374 | 1375 | ``` 1376 | val lega = fn e:ambiente => fn nome => fn valore => (fn n => if (n = nome) 1377 | then 1378 | (Int valore) 1379 | else 1380 | (e n)):ambiente; 1381 | ``` 1382 | 1383 | ##### Testing (Non fa parte della soluzione - utile per capire) 1384 | 1385 | ``` 1386 | ((lega ambientevuoto "a"1)"a"); 1387 | ((lega ambientevuoto "a"1)"boh"); 1388 | ((lega (lega ambientevuoto "a"1)"boh"~1)"boh"); 1389 | ((lega (lega ambientevuoto "a"1)"boh"~1)"mah"); 1390 | ``` 1391 | 1392 | ### Esame giugno 2023 1393 | 1394 | ##### Testo 1395 | 1396 | Scrivere una **curried function “f”** che prenda in input una lista di stringhe[ai, ai+1, …] e un intero n. 1397 | La funzione deve ritornare una lista di stringhe[bi, bi+1, …] in cui 1398 | - bi è uguale ad ai solo se la lunghezza di ai è minore o uguale ad n, 1399 | - altrimenti bi è uguale ad ai senza il primo carattere. 1400 | 1401 | Esempio: 1402 | 1403 | >f [" ", "ab", "abc", "abcd", "abcde"] 3; 1404 | val it = [" ", "ab", "abc", "bcd", "bcde"]: string list 1405 | 1406 | ##### Soluzione 1407 | 1408 | ``` 1409 | fun f (nil) n = nil 1410 | | f (a::l) n = if (length (explode a) <= n) 1411 | then 1412 | a::(f (l) n) 1413 | else 1414 | implode(tl(explode(a)))::(f (l) n); 1415 | ``` 1416 | 1417 | ##### Testing (Non fa parte della soluzione - utile per capire) 1418 | 1419 | ``` 1420 | f [" ", "ab", "abc", "abcd", "abcde"] 3; 1421 | ``` 1422 | 1423 | 1424 | ### Esame luglio 2023 1425 | 1426 | ##### Testo 1427 | 1428 | Si scriva una funzione **conta_duplicati** (avente tipo `''a list -> (''a * int) list`) che riceve come argomento una lista di `''a` e restituisce una `lista di tuple ''a * int`. 1429 | 1430 | La funzione **conta_duplicati** ritorna una lista di coppie (elemento, numero di occorrenze dell'elemento), cioè per ogni elemento distinto e della lista di input, la lista di output contiene una coppia (e, numero di occorrenze di e). 1431 | 1432 | Come esempio, l'invocazione: 1433 | - `conta_duplicati [2, 2, 2, 2];` deve avere risultato [(2,4)], 1434 | - `conta_duplicati ["lunedi'", "lunedi'", "martedi'", "lunedi'"];` deve avere risultato [("lunedi'",3), ("martedi'",1)], 1435 | - `conta_duplicati ["blu", "verde", "verde", "blu", "rosso"];` deve avere risultato [("blu",2), ("verde",2), ("rosso",1)] 1436 | 1437 | **IMPORTANTE**: notare il tipo della funzione! 1438 | 1439 | L'**ordine delle coppie** all'interno della lista risultante **non** è rilevante. 1440 | 1441 | La funzione **conta_duplicati** deve essere definita in un file .sml autocontenuto ma **separato da qualsiasi codice di test si sia usato**. 1442 | Il file .sml deve contenere la chiamata a **conta_duplicati**. Si consegni il file .sml contenente la definizione di **conta_duplicati** rinominandolo *Cognome_Nome_Matricola.sml*. 1443 | 1444 | ##### Soluzione 1445 | 1446 | ``` 1447 | fun conta_duplicati(L) = 1448 | let 1449 | fun estrai [] = nil 1450 | | estrai (x::y) = 1451 | if(List.exists(fn a => a = x) y) then 1452 | estrai y 1453 | else 1454 | x::estrai y; 1455 | 1456 | val duplicati = estrai L; 1457 | 1458 | fun conta s [] = 0 1459 | | conta s (x::y) = 1460 | if s = x then 1 + conta s y 1461 | else conta s y; 1462 | 1463 | fun tuple [] = nil 1464 | | tuple (x::y) = (x, conta x L)::tuple y; 1465 | 1466 | in 1467 | tuple duplicati 1468 | end; 1469 | ``` 1470 | 1471 | ##### Testing (Non fa parte della soluzione - utile per capire) 1472 | 1473 | ``` 1474 | conta_duplicati [2, 2, 2, 2]; 1475 | conta_duplicati ["lunedi'", "lunedi'", "martedi'", "lunedi'"]; 1476 | conta_duplicati ["blu", "verde", "verde", "blu", "rosso"]; 1477 | conta_duplicati [1]; 1478 | conta_duplicati [1,1,1,1,1,1,1,1,1,1]; 1479 | ``` 1480 | 1481 | ### Esame gennaio 2024 1482 | 1483 | ##### Testo 1484 | 1485 | Scrivere una funzione **suffixes** (di tipo `string -> string list`) che presa in input una stringa, ritorni una lista di tutti i suffissi della stringa, compresa la stringa stessa ed esclusa la stringa vuota. 1486 | _nota: esista una funzione map che permette appendere un elemento a ogni elementi da lista_ 1487 | 1488 | ##### Esempi: 1489 | 1490 | > \> suffixes "ciao"; 1491 | val it : ["ciao" , "cia", "ci", "ci", "c"]; 1492 | 1493 | > \> suffixes ""; 1494 | val it : []; 1495 | 1496 | > \> suffixes "hi world"; 1497 | val it : ["hi world","hi worl","hi wor","hi wo","hi w","hi ","hi","h"]; 1498 | 1499 | ##### Soluzione 1500 | 1501 | ``` 1502 | fun suffixes s = 1503 | let 1504 | fun helper (str, acc) = 1505 | if str = "" then 1506 | List.rev acc 1507 | else 1508 | helper (String.extract (str, 1, NONE), str :: acc) 1509 | in 1510 | helper (s, []) 1511 | end; 1512 | ``` 1513 | 1514 | oppure 1515 | 1516 | ``` 1517 | fun suffixes "" = [] 1518 | | suffixes s = s :: suffixes (String.extract (s, 0, SOME (size s - 1))); 1519 | ``` 1520 | 1521 | ##### Testing (Non fa parte della soluzione - utile per capire) 1522 | 1523 | ``` 1524 | suffixes "ciao"; 1525 | suffixes ""; 1526 | suffixes "hi world"; 1527 | suffixes "test 123 4"; 1528 | ``` 1529 | 1530 | ### Esame febbraio 2024 1531 | 1532 | ##### Testo 1533 | 1534 | Scrivere una funzione **prefixes** (di tipo `string -> string list`) che presa in input una stringa, ritorni una lista di tutti i prefissi della stringa, compresa la stringa stessa ed esclusa la stringa vuota. 1535 | _nota: esista una funzione map che permette appendere un elemento a ogni elementi da lista_ 1536 | 1537 | ##### Esempi: 1538 | 1539 | > \> prefixes "ciao"; 1540 | val it : ["c" , "ci", "cia", "ciao"]; 1541 | 1542 | > \> prefixes ""; 1543 | val it : []; 1544 | 1545 | > \> prefixes "hi world"; 1546 | val it : ["h", "hi", "hi ", "hi w", "hi wo", "hi wor", "hi worl", "hi world"]; 1547 | 1548 | ##### Soluzione 1549 | 1550 | ``` 1551 | fun prefixes s = 1552 | (* Helper function that generates the prefixes by using an index *) 1553 | let 1554 | (* Inner recursive function that constructs the prefix list *) 1555 | fun helper (str, len) = 1556 | if len = String.size str then 1557 | [str] (* If the length equals the size of the string, return the string as the final prefix *) 1558 | else 1559 | String.substring(str, 0, len) :: helper (str, len + 1) 1560 | in 1561 | if s = "" then [] (* If the input string is empty, return an empty list *) 1562 | else helper (s, 1) (* Otherwise, start generating prefixes from length 1 *) 1563 | end; 1564 | ``` 1565 | 1566 | oppure 1567 | 1568 | ``` 1569 | fun prefixes s = 1570 | let 1571 | fun helper (str, acc, n) = 1572 | if n > String.size str then 1573 | List.rev acc 1574 | else 1575 | helper (str, (String.substring (str, 0, n)) :: acc, n + 1) 1576 | in 1577 | helper (s, [], 1) 1578 | end; 1579 | ``` 1580 | 1581 | ##### Testing (Non fa parte della soluzione - utile per capire) 1582 | 1583 | ``` 1584 | prefixes "ciao"; 1585 | prefixes ""; 1586 | prefixes "hi world"; 1587 | prefixes "test 123"; 1588 | ``` 1589 | 1590 | ### Esame giugno 2024 1591 | 1592 | ##### Testo 1593 | 1594 | L'esercizio consiste nell'implementare la funzione **sum_binary** di tipo `int list * int list -> int list` che implementa l'operazione di somma binaria. 1595 | Nel programma **NON** è permesso l'utilizzo di operatori aritmetici **(+)** ma si possono usare gate come andalso oppure orelse. Si possono utilizzare funzioni di supporto. 1596 | 1597 | ##### Esempi: 1598 | 1599 | > \> sum_binary([],[]); 1600 | val it = []: int list; 1601 | 1602 | > \> sum_binary([1,0],[1]); 1603 | val it = [1, 1]: int list; 1604 | 1605 | > \> sum_binary([1,0,0,1],[1,1,0]); 1606 | val it = [1, 1, 1, 1]: int list; 1607 | 1608 | > \> sum_binary([1],[1,1]); 1609 | val it = [1, 0, 0]: int list; 1610 | 1611 | > \> sum_binary([1,1,0,0,1,1],[1,0,1,0]); 1612 | val it = [1, 1, 1, 1, 0, 1]: int list; 1613 | 1614 | > \> sum_binary([1,0,0,1,1],[1,1,1,0,1]); 1615 | val it = [1, 1, 0, 0, 0, 0]: int list; 1616 | 1617 | ##### Soluzione 1618 | 1619 | ``` 1620 | fun orgate (0,0) = 0 | orgate (_,_) = 1; 1621 | 1622 | fun appo (nil,nil,true) = [1] 1623 | | appo (nil,nil,false) = [0] 1624 | | appo (nil,L,true) = appo([0],L,true) 1625 | | appo (L,nil,true) = appo(L,[0],true) 1626 | | appo (nil,L,false) = L 1627 | | appo (L,nil,false) = L 1628 | | appo (L,nil,_) = L 1629 | | appo (L1,L2,carry) = if (hd(L1) = 1 andalso hd(L2) = 1) 1630 | then (if carry = true 1631 | then 1::appo(tl(L1),tl(L2),true) 1632 | else 0::appo(tl(L1),tl(L2),true) ) 1633 | else (if carry = true 1634 | then if ((hd(L1) = 1 andalso hd(L2) = 0) orelse (hd(L1) = 0 andalso hd(L2) = 1)) 1635 | then 0::appo(tl(L1),tl(L2),true) 1636 | else 1::appo(tl(L1),tl(L2),false) 1637 | else orgate(hd(L1),hd(L2))::appo(tl(L1),tl(L2),false)); 1638 | 1639 | fun sum_binary (nil,L) = L | sum_binary(L,nil) = L | sum_binary (L1,L2) = 1640 | let 1641 | val R1 = List.rev(L1); 1642 | val R2 = List.rev(L2); 1643 | in 1644 | List.rev(appo(R1,R2,false)) 1645 | end; 1646 | 1647 | ``` 1648 | 1649 | ##### Testing (Non fa parte della soluzione - utile per capire) 1650 | 1651 | ``` 1652 | sum_binary([],[]); 1653 | sum_binary([1,0],[1]); 1654 | sum_binary([1,0,0,1],[1,1,0]); 1655 | sum_binary([1],[1,1]); 1656 | sum_binary([1,1,0,0,1,1],[1,0,1,0]); 1657 | sum_binary([1,0,0,1,1],[1,1,1,0,1]); 1658 | ``` --------------------------------------------------------------------------------