Prof. Dr. Manfred Schmidt-Schauß Künstliche Intelligenz/Softwaretechnologie Fachbereich Informatik und Mathematik/ Institut für Informatik Goethe-Universität Frankfurt am Main Grundlagen der Programmierung 2 Sommersemester 2013 Aufgabenblatt Nr. 5 Abgabe: Mittwoch 22. Mai 2013 vor! der Vorlesung Aufgabe 1 (40 Punkte) Binäre Bäume mit (polymorphen) Markierungen aller Knoten können in Haskell definiert werden durch den folgenden rekursiven Datentyp Baum: data Baum a = Blatt a | Knoten (Baum a) a (Baum a) deriving(Eq,Show) Ein Beispiel ist der folgende Baum und dessen Darstellung als Baum Integer: baum = Knoten (Knoten 5 (Blatt (-8)) (-12) -12 14 (Knoten (Blatt 9) 3 (Blatt 6))) 5 -8 3 2 -2 (Knoten (Blatt 2) 9 6 14 (Blatt (-2))) a) Implementieren Sie in Haskell eine Funktion maxMarkierung :: (Baum Integer) -> Integer, die einen binären Baum mit Ganzzahlen als Markierungen erhält und das Maximum der Markierungen berechnet. Für obiges Beispiel würde maxMarkierung baum die Zahl 14 als Ergebnis liefern. (10 Punkte) b) Das Gewicht eines Knotens im binären Baum sei die Summe aller Knotenmarkierungen aller Nachfahren des Knotens. Blätter haben stets das Gewicht 0. Im obigen Beispiel hat der Knoten mit Markierung -12 das Gewicht 10 (= -8 + 3 + 9 + 6), der Knoten mit Markierung 14 das Gewicht 0 (= -2 + 2), der Knoten mit Markierung 5 das Gewicht 12 usw. Implementieren Sie eine Funktion gewichte :: (Baum Integer) -> Baum (Integer,Integer), die einen Baum erwartet und jede Knotenmarkierung a durch das Paar (a, b) ersetzt, wobei b das Gewicht des Knotens ist. (15 Punkte) c) Eine Verdrehung am Knoten mit Markierung a vertauscht den linken und den rechten Unterbaum des Knotens a miteinander (wie die Abbildung rechts illustriert). Zwei Bäume seien isomporph, wenn sie durch Verdrehungen an beliebigen Knoten ineinander überführt werden können. a a Implementieren Sie eine Funktion testeIsomorphie :: Baum Integer -> Baum Integer -> Bool, die als Eingaben zwei Bäume erwartet und prüft, ob die beiden Bäume isomorph sind. (15 Punkte) 1 Aufgabe 2 (15 Punkte) Geben Sie für jeden der folgenden Typen eine Funktion in Haskell an, deren allgemeinster Typ genau der genannte Typ ist. a) Bool -> (Char,Bool) (3 Punkte) b) [(a,a)] -> [(a,a,a)] (4 Punkte) c) [a] -> [b] -> [(b,[a])] (4 Punkte) d) [[([Char],a,b)]] -> (a -> b -> Char) -> ([Char], b -> a -> Char) (4 Punkte) Gehen Sie dabei folgendermaßen vor: Definieren Sie in einer Quelltextdatei die Funktionen aufgabeA, aufgabeB, aufgabeC und aufgabeD ohne deren Typ anzugeben. Laden Sie anschließend die Datei in den ghci und lassen Sie sich den Typ der Funktionen berechnen: Dafür geben Sie (für Aufgabe a)) :type aufgabeA im Interpreter ein. Wenn der angezeigte Typ dem Typ der Aufgabenstellung (bis auf Umbenennung der Typvariablen) entspricht, haben Sie die Aufgabe gelöst. Sei z.B. die gesuchte Funktion vom Typ a -> (Bool,Bool), so kann man definieren: beispiel x = (False,True) Der ghci liefert dann als Typ: :type beispiel beispiel :: t -> (Bool, Bool) Daher hat beispiel den gesuchten Typ (Umbenennung der Typvariablen t durch a ist erlaubt). Aufgabe 3 (45 Punkte) Berechnen (Rechenweg erforderlich!) Sie jeweils den (polymorphen) Typ der folgenden Ausdrücke: a) (map take) (12 Punkte) b) (flip const) (13 Punkte) c) on (flip const) (map take) (20 Punkte) mithilfe der in der Vorlesung vorgestellten Typregeln. Sie können dabei die Typen für map, take, const, on1 und flip sowie Ihre Ergebnisse verwenden, ohne diese (erneut) herzuleiten. Die Typen sind: map take const flip on :: :: :: :: :: (a -> b) -> [a] -> [b] Int -> [c] -> [c] d -> e -> d (f -> g -> h) -> g -> f -> h (i -> i -> j) -> (k -> i) -> k -> k -> j Beachten Sie, dass Sie bei Verwendung der Anwendungsregel auch die Typsubstitution mithilfe von Unifikation berechnen müssen. 1 on ist in der Bibliothek Data.Function definiert. 2