Esercizi svolti nella Lezione del 13/06/2012 Esercizio 1 (tempo
Transcript
Esercizi svolti nella Lezione del 13/06/2012 Esercizio 1 (tempo
Esercizi svolti nella Lezione del 13/06/2012 Esercizio 1 (tempo previsto: 20’): Scrivere in Scheme (o, se si preferisce, in Lisp) una funzione split che prende in input una lista di interi l e restituisce in output la lista l con i numeri pari che precedono i numeri dispari nello stesso ordinamento con cui i numeri compaiono in l. Si consiglia la definizione di funzioni ausiliarie per l’implementazione di split. NOTA: l’utilizzo dell’operatore Lisp/Scheme modulo non è ammesso per determinare se un intero è pari o dispari. La lista può contenere sia interi positivi sia negativi (e anche doppioni). Si consideri lo 0 come un intero pari. esempio: (split ‘(3 0 -73 6 -24 6 2)) restituisce: (0 6 -24 6 2 3 -73) Esercizio 2 (tempo previsto: 10’): Mostrare cosa stampa in output ML nel valutare le seguenti istruzioni. Se non si ricorda la sintassi dei messaggi di output di ML è sufficiente specificare il risultato della valutazione dell’istruzione (e.g., identificatore con valore 5, puntatore al valore 7, il numero 3, funzione, etc.), e il tipo del risultato (e.g., int, puntatore a real, bool*int->real, etc.). In caso di errore, specificare il motivo per cui la valutazione dell’istruzione ha terminato in un errore. In caso di non terminazione, specificarne la causa. Ogni istruzione va valutata tenendo conto dell’ambiente modificato dalle precedenti istruzioni. val x = 5; ________________________________________ val y = ref (ref (ref x)); _________________________________ let val y = 8 in let val y = 5 and z = 3 in y * z end end; ___________________________________________________________________ fun inc(y) = y + 1; ________________________________________ fun inc(f) = f(x); ________________________________________ inc(4); ________________________________________ inc(inc); ________________________________________ fun twice(y) = y * 2; ________________________________________ inc(twice); ________________________________________ Esercizio 3 (tempo previsto: 20’): Data le seguente definizione di tipo di dato astratto: datatype intTree = ifoglia of int | inodo of int * intTree * intTree; scrivere una funzione t2l_sort che prende in input un albero A di tipo intTree e ritorna in output un lista B di interi dove gli elementi in B sono le etichette dei nodi contenuti in A e sono ordinati in modo crescente. Si consiglia la definizione di funzioni ausiliare per l’implementazione di t2l_sort. NOTA: i pattern match che si usano nella definizione delle varie funzioni devono essere tutti esaustivi (ovvero non si accetta la definizione di funzioni parziali). esempio: t2l_sort( restituisce: inodo(3, inodo(0,ifoglia(73),ifoglia(6)), inodo(24,i foglia(6),ifoglia(2)))) [0 2 3 6 6 24 73] Esercizio 4 (tempo previsto: 20’): Data la seguente funzione ML: fun g([x]) = x | g(x::l) = if x < g(l) then x else g(l); cosa calcola g e quale è il suo tipo. Inoltre dire, motivando dire la risposta, se g è una funzione parziale o totale. Nel caso si riscontri che g è una funzione parziale, dire se in ML c’è un modo per considerare anche i casi in cui la funzione g possa essere invocata su argomenti per cui essa non è semanticamente definibile in modo corretto. Motivare la risposta fornendo del codice esemplificativo (si prenda in considerazione la possibilità di poter aggiungere, se si ritiene opportuno, nuovi pattern matches al codice di g sopra riportato). Esercizio 5 (tempo previsto: 20’): Date le seguenti definizioni di classe in C++ class A { public: virtual void print() { std::cout << "Ciao da A\n"; } }; class B { public: virtual void print() { std::cout << "Ciao da B\n"; } }; class C: public A, B { public: virtual void print() { std::cout << "Ciao da C\n"; } }; dire se il compilatore C++ riesce a compilare il seguente main program oppure no. Motivare opportunamente la risposta. Solo nel caso in cui si ritenga che il compilatore non ritorni errori, dire cosa stampa la chiamata al metodo print. Motivare opportunamente la risposta. int main (int argc, char * const argv[]) { B *b = new B(); C *c = new C(); b = c; b->print(); return 0; } Esercizi svolti nella Lezione del 14/06/2012 Esercizio 1 (tempo previsto: 30’). Scrivere in Scheme o in Lisp una funzione estrai_e_alterna che, data una lista L di numeri naturali (ovvero numeri interi >= 0) e dato un intero N >= 0, restituisce la lista M che contiene tutti i numeri di L che sono multipli di N elencati alternando i multipli pari con i multipli dispari nel seguente modo: (primo_multiplo_pari primo_multiplo_dispari secondo_multiplo_pari secondo_multiplo_dispari ….). Ad esempio se in input viene passata la lista '(2 3 4 9 1 6) e l’intero 3, in output viene restituita la lista '(6 3 9). NOTA: al fine di non rendere l’esercizio triviale, la funzione modulo fornita direttamente da Scheme/Lisp non può essere utilizzata per controllare se un numero è pari o dispari, o se un numero è multiplo di un altro. Pertanto, se lo studente ritiene di dover utilizzare una funzione equivalente a modulo, essa deve essere definita dallo studente stesso. Esercizio 2 (tempo previsto: 15’). Mostrare cosa stampa in output ML nel valutare le seguenti istruzioni. NOTA: se non si ricorda la sintassi dei messaggi di output di ML è sufficiente specificare il risultato della valutazione dell’istruzione (e.g., identificatore con valore 5, puntatore al valore 7, il numero 3, funzione, etc.), e il tipo del risultato (e.g., int, puntatore a real, bool*int->real, etc.). In caso di errore, specificare il motivo per cui la valutazione dell’istruzione ha terminato in un errore. In caso di non terminazione, specificarne la causa. Ogni istruzione va valutata tenendo conto dell’ambiente modificato dalle precedenti istruzioni. - val x = 3; _____________________________________________ - val y = (ref x); _____________________________________________ - val ref z = ref (ref y); ___________________________________________________________________ - val k = let val k = !(!z) and z=7 in fn g => g(fn z => z + k) + z end; ___________________________________ - fun f(k) = !k(x); _____________________________________________ - k(fn x => x + 1); _____________________________________________ - fun g(h, a) = fn k => (fn nil => nil | b::m => k(b)::h(a)); ___________________________________________________________________ Esercizio 3 (tempo previsto: 25’). Sia dato uno stack definito dalla seguente definizione di tipo in ML: datatype 'a stack = Empty | elem of 'a | stack of 'a * 'a stack; e la definizione dell’eccezione EmptyExc: exception EmptyExc; a. Scrivere una funzione pop che prende in input uno stack di tipo ‘a stack e torna, se lo stack ha almeno un elemento, una coppia costituita dall’elemento al top dello stack e lo stack con l’elemento al top cancellato, oppure, se lo stack è vuoto, solleva l’eccezione EmptyExc. b. Dare il tipo della funzione pop. Esercizio 4 (tempo previsto: 15’). Dato il seguente codice C++: class B { public : B() { Init(); } virtual void Init() { cout << "B::B()" << endl; } }; class D : private B { public : D() { Init(); } virtual void Init() { cout << "D::D()" << endl; } }; int main(int argc, char *argv[]) { D *objD = new D(); } dire se il programma viene compilato correttamente o se ci sono errori a tempo di compilazione. Se si riscontra che non ci sono errori a tempo di compilazione, dire se il programma presenta errori durante l’esecuzione oppure no. Se si riscontra che il programma esegue correttamente, dire cosa stampa in output. Si motivino tutte le risposte in modo chiaro ed esaustivo.