Matrikelnummer: 1 Aufgabe 1 Basiswissen zur Vorlesung (8 Punkte) Kreuzen Sie an, ob die folgenden Aussagen richtig oder falsch sind. Bewertung: keine Antwort: 0 Punkte richtige Antwort: +0.5 Punkte falsche Antwort: 0.5 Punkte Für diese Aufgabe werden mindestens 0 Punkte vergeben. wahr falsch Eine Entwurfsbeschreibung beschreibt ein zu entwickelndes Software-System umfassender und in vielen Fällen auch präziser als eine Anforderungsbeschreibung. Eine Grammatik kann eine Sprache beschreiben, die unendlich viele Sätze enthält. Eine kontextfreie Grammatik lässt sich durch ein Tripel aus Terminalen, Nichtterminalen und Produktionsregeln definieren. Zu einer kontextfreien Sprache kann es mehrere Grammatiken geben. Kontextfreie Grammatiken sind immer eindeutig. Zwischen Syntax und Semantik kann auch in natürlichen Sprachen unterschieden werden. Syntax ordnet den Elementen einer formalen Sprache eine Bedeutung zu. Jede Funktion vom Typ a int ist auch vom Typ a int. Dieses Programmstück ist nicht typkorrekt: (val x = 5; val x = true) Das ML-Sprachkonstrukt case-of erlaubt dem Programmierer das Pattern-Matching innerhalb einer Funktionsdeklaration anzuwenden. Die Wertemengen zu den Typen int und real sind nicht disjunkt. In einer repetitiv rekursiven Deklaration einer Funktion f kann f auf der rechten Seite der Deklaration erscheinen. Prozedurale Sprachen erlauben keine Typdeklarationen. Die Ausführung einer Anweisung in Java terminiert immer. Sei x ein Stapel: pop(pop(push(5,x))) ist immer definiert! Es gilt O(n log 10 n) = O(n log 2 n).
Matrikelnummer: 2 Aufgabe 2 Funktionale Programmierung mit Listen (12 Punkte) a) Schreiben Sie eine ML-Funktion take : int a list a list, die eine ganze nichtnegative Zahl i und eine Liste l als Parameter entgegennimmt und die ersten i Elemente von l in einer Liste l zurückgibt. Dabei sollen die Elemente von l in der gleichen Reihenfolge, in der sie in l vorkommen, angeordnet sein. Ist i gleich 0, dann liefere der Aufruf take 0 l die leere Liste. Ist i grösser als die Länge von l, dann liefere der Aufruf take i l die Liste l. (2 Punkte) take 0 [2,3] = [] take 3 [2,3] = [2,3] take 3 [#"L",#"i",#"s",#"t",#"e"] = [#"L",#"i",#"s"] fun take 0 l = [] take n l = case l of [] => [] (x::xs) => (x::(take (n-1) xs)) b) Schreiben Sie eine ML-Funktion test : string bool, die eine Zeichenreihe str als Parameter entgegennimmt und entscheidet, ob in str die Zeichenreihe "abc" vorkommt. (3 Punkte) test "Milchbar" = false test "Cevabcici" = true fun test str = (case (explode str) of (a::b::c::xs) => (if (a=(#"a")) andalso (b=(#"b")) andalso (c=(#"c")) then true else (test (implode(b::c::xs)))) _ => false)
Matrikelnummer: 3 c) Schreiben Sie eine ML-Funktion det : int list list int, welche die Determinante einer Matrix der Dimension 2 2 berechnet. Dabei ist die Determinante D einer Matrix der Dimension 2 2 folgendermaßen definiert: ( ) a b D = (a d) (b c) c d Eine Matrix der Dimension 2 2 wird als eine Liste von Listen von ganzen Zahlen repräsentiert. (2 Punkte) Beispiel: ( ) 2 3 als [[2, 3], [5, 9]] 5 9 fun det [[a,b],[c,d]] = (a*d)-(b*c) d) Schreiben Sie eine ML-Funktion sort : (int int) list (int int) list, die eine Liste von Zahlenpaaren l = [(i 0, i 0 ), (i 1, i 1 ),..., (i n, i n )] als Parameter entgegennimmt und diese nach den folgendgen Kriterien sortiert: 1. Gibt es in der Liste l zwei Paare (i j, i j ) und (i k, i k ) mit i j < i k, dann soll (i j, i j ) in der sortierten Liste vor (i k, i k ) vorkommen. 2. Gibt es in l zwei Paare (i j, i j ) und (i k, i k ) mit i j = i k und i j < i k, dann soll (i j, i j ) in der sortierten Liste vor (i k, i k ) vorkommen. (5 Punkte) sort [] = [] sort [(2,7),(1,2),(3,8),(1,3),(3,9),(1,1)] = [(1,1),(1,2),(1,3),(2,7),(3,8),(3,9)] sort [(7,4),(7,2),(7,5),(7,2)] = [(7,2),(7,2),(7,4),(7,5)] fun tupelord (a,b) (aa,bb) = case Int.compare(a,aa) of LESS => LESS GREATER => GREATER EQUAL => Int.compare(b,bb) fun einfuegen t [] = [t] einfuegen t (x::xs) = case (tupelord t x) of LESS => (t::x::xs) _ => (x::(einfuegen t xs)) fun sort l = let fun sort_ l1 [] = l1 sort_ l1 (x::xs) = sort_ (einfuegen x l1) xs in sort_ [] l end
Matrikelnummer: 4 Aufgabe 3 Funktionale Programmierung mit Bäumen (11 Punkte) In dieser Aufgabe modellieren wir die Menge der binären Bäume mit der folgenden Datentypdeklaration: datatype bintree = Node of int * bintree * bintree Leaf a) Schreiben Sie eine ML-Funktion height : bintree int, die einen binären Baum t als Parameter entgegennimmt und die Höhe des Baumes t berechnet. (3 Punkte) height Leaf = 0 height (Node(7,Leaf,Leaf)) = 1 height (Node(7,Leaf,Node(8,Leaf,Node(9,Leaf,Leaf)))) = 3 fun det [[a,b],[c,d]] = (a*d)-(b*c) (* Aufgabe 2c *) fun test str = (case (explode str) of b) Schreiben Sie eine ML-Funktion leafnumb : bintree int, die einen binären Baum t als Parameter entgegennimmt und die Anzahl der Blätter in t berechnet. (3 Punkte) leafnumb Leaf = 1 leafnumb (Node(7,Leaf,Leaf)) = 2 leafnumb (Node(7,Node(6,Leaf,Leaf), Node(8,Leaf,Leaf))) = 4 _ => false) (c=(#"c")) then true else (test (implode(b::c::xs))))
Matrikelnummer: 5 c) Schreiben Sie eine ML-Funktion heapeigenschaft : bintree bool, die einen Baum t vom Typ bintree als Parameter entgegennimmt und überprüft, ob t ein vollständiger binärer Baum mit der Heap-Eigenschaft ist. (5 Punkte) heapeigenschaft Leaf = true heapeigenschaft (Node(3,Leaf,Leaf)) = true heapeigenschaft (Node(33,Node(20,Leaf), Node(32,Leaf))) = true heapeigenschaft (Node(33,Node(20,Leaf), Node(34,Leaf))) = false fun tupelord (a,b) (aa,bb) = case Int.compare(a,aa) of LESS => LESS GREATER => GREATER EQUAL => Int.compare(b,bb) fun einfuegen t [] = [t] einfuegen t (x::xs) = case (tupelord t x) of LESS => (t::x::xs) _ => (x::(einfuegen t xs))
Matrikelnummer: 6 Aufgabe 4 Terminierungsbeweis (4 Punkte) Betrachten Sie die folgenden Deklarationen des Datentyps bintree und der Funktion spiegelung: datatype bintree = Node of bintree * bintree Leaf of int fun spiegelung Leaf(c) = Leaf(c) spiegelung Node(t1,t2) = Node(spiegelung t2, spiegelung t1) Beweisen Sie die Terminierung der Funktion spiegelung. Verwenden Sie hierzu das in der Vorlesung vorgestellte Beweisverfahren (mit noetherscher Ordnung). Eine informelle Beschreibung der Beweisidee ist nicht ausreichend. Lösung: Wähle P als die Menge der endlichen Bäume vom Typ bintree. Wähle (N, ) als noethersche Ordnung. Als δ wähle die Funktion height : bintree int, die einen binären Baum t als Argument entgegennimmt und die Höhe von t berechnet. Zu zeigen: i) t 1 und t 2 sind zulässige Parameter in den Funktionsaufrufen spiegelung(t 1 ) und spiegelung(t 2 ): ok. ii) height(t 1 ) < height(node(t 1,t 2 )) und height(t 2 ) < height(node(t 1,t 2 )): ok. Damit ist die Terminierung der Funktion spiegelung gezeigt.
Matrikelnummer: 7 Aufgabe 5 O-Notation (8 Punkte) Gegeben ist folgendes Programmfragment: int[] insert (int element,int[] array) {... a) Die Funktionsprozedur insert bekommt ein Element und ein sortiertes Feld (array) als Parameter übergeben. Zurückgegeben werden soll ein neues, sortiertes Array, das das neue Element und alle Elemente aus array enthält. Ergänzen Sie insert entsprechend. Hinweis: array.length liefert die Länge des Feldes array zurück. (4 Punkte) int[] insert (int element,int[] array) { int[] tarray = new int[array.length + 1]; int i = 0; while (i < array.length && array[i] < element) { tarray[i] = array[i]; i++; tarray[i] = element; while (i < array.length) { tarray[i+1] = array[i]; i++; return tarray; b) Wie verhält sich Ihre Lösung in den Fällen, in denen das neue element kleiner bzw. größer als alle vorhandenen Elemente im array ist? (2 Punkte) Es gibt keinen Unterschied, in beiden Fällen wird das gesamte Feld kopiert c) Welchen Aufwand hat Ihre Lösung in Abhängigkeit von der Länge l des Feldes array und der Anzahl an Zuweisungen an Feldkomponenten? Geben Sie eine Funktion an, die die Anzahl der Zuweisungen zurückgibt, und geben Sie den Aufwand Ihrer Lösung in der O-Notation an. (2 Punkte) F(l) = l+1 bzw. O(l)
Matrikelnummer: 8 Aufgabe 6 Eigenschaften von Programmen (7 Punkte) Gegeben sind folgende Programmteile: class DataSet { int key; char c; void p (DataSet[] a) { int t; for (int i = 0;...) { for (int j =...;...) { if (...) {... a) Ergänzen Sie die Prozedur p so, dass das Feld a sortiert wird (möglich ist zum Beispiel ein Sortierverfahren aus der Vorlesung). (4 Punkte) class DataSet { int key; char c; void p (DataSet[]a) { int t; for (int i = 0;i < a.length -1;i++) { for (int j = i+1; j < a.length -1;j++) { if (a[i].key < a[j].key) { DataSet t2; t2 = a[i]; a[i] = a[j]; a[j] = t2;
Matrikelnummer: 9 b) Stellen Sie in der grafischen Notation der Vorlesung die drei wichtigsten Schritte beim Sortieren der drei Elemente (42, c ),(10, a ), (12, b ) dar (Anfangszustand, Endzustand und einen weiteren Zustand). (3 Punkte) Darzustellen sind die Zustände für: (42, c ),(10, a ),(12, b ); (10, a ),(42, c ),(12, b ); (10, a ),(12, b ),(42, c )