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 2014 Aufgabenblatt Nr. 2 Abgabe: Mittwoch 30. April 2014 vor! der Vorlesung Aufgabe 1 (35 Punkte) In dieser Aufgabe betrachten wir Eltern-Kind-Beziehungen. Diese seien in Haskell durch die drei Funktionen elternBekannt :: String -> Bool, vater :: String -> String und mutter :: String -> String modelliert, wobei: • elternBekannt gibt für eine Person an, ob dessen Vater und Mutter bekannt sind. • vater bzw. mutter berechnet den Vater bzw. die Mutter eines Kindes, sofern diese(r) bekannt ist (und gibt sonst einen Fehler aus). Die drei Funktionen seien bereits im Quellcode definiert. Z.B. könnte der Stammbaum Axel Berta Claudia Detlef m m Carl Bruno m Anna Bert Albert Birgit Clemens m Clara Dirk Dominik m Adele Bastian m Curt Diana durch die folgende Haskell-Implementierung repräsentiert werden (das Beispiel finden Sie zum Download als Haskell-Quellcode auf der Webseite zur PRG-2): elternBekannt elternBekannt elternBekannt elternBekannt elternBekannt elternBekannt elternBekannt elternBekannt "Axel" "Anna" "Albert" "Adele" "Berta" "Claudia" "Curt" _ = = = = = = = = False False False False False False False True mutter "Bruno" = "Anna" mutter "Bert" = "Anna" mutter "Birgit" = "Anna" mutter "Bastian" = "Adele" mutter "Carl" = "Berta" mutter "Clemens" = "Berta" mutter "Clara" = "Birgit" mutter "Detlef" = "Claudia" mutter "Dirk" = "Claudia" mutter "Dominik" = "Clara" mutter "Diana" = "Clara" mutter _ = error "Mutter unbekannt" vater "Bruno" = "Axel" vater "Bert" = "Axel" vater "Birgit" = "Axel" vater "Bastian" = "Albert" vater "Carl" = "Bruno" vater "Clemens" = "Bruno" vater "Clara" = "Bastian" vater "Detlef" = "Carl" vater "Dirk" = "Carl" vater "Dominik" = "Curt" vater "Diana" = "Curt" vater _ = error "Vater unbekannt" In den Teilaufgaben müssen Sie Funktionen definieren. Diese dürfen vater, mutter und elternBekannt aufrufen, aber müssen für jede Implementierung dieser Funktionen funktionieren, d.h. nicht ausschließlich für obiges Beispiel!. 1 Implementieren Sie in Haskell a) eine Funktion mindestensEineGrossmutterBekannt :: String -> Bool, die für eine Person prüft, ob der Name mindestens einer Großmutter bekannt ist, und in diesem Fall True und ansonsten False als Ausgabe liefert. (5 Punkte) b) eine Funktion istVorfahre :: String -> String -> Bool, die zwei Personen P1 und P2 als Eingaben erhält und True liefert, wenn P1 ein Vorfahre von P2 ist, und in allen anderen Fällen (P1 ist kein Vorfahre von P2 oder es ist unbekannt) den Wert False liefert. (10 Punkte) c) eine Funktion sindGeschwister :: String -> String -> Bool, die für zwei Personen P1 und P2 überprüft, ob diese Geschwister sind, d.h. ob P1 und P2 sowohl den gleichen Vater als auch die gleiche Mutter haben. (5 Punkte) d) eine Funktion istCousinOderCousine :: String -> String -> Bool, die zwei Personen P1 und P2 erwartet und True liefert, wenn P1 ein Cousin oder eine Cousine von P2 ist, und in allen anderen Fällen False liefert. P1 ist Cousin oder Cousine von P2 , wenn P2 ein Kind eines Onkels oder einer Tante von P1 ist, oder anders formuliert, wenn ein Elternteil von P1 und ein Elternteil von P2 Geschwister sind. (8 Punkte) e) eine Funktion sindVerwandt :: String -> String -> Bool, die die zwei Personen P1 und P2 erwartet und True liefert, wenn P1 und P2 verwandt sind, d.h. P1 und P2 haben einen gemeinsamen Vorfahren. Sie können hier annehmen, dass jeder mit sich selbst verwandt ist. (7 Punkte) Einige Beispielaufrufe der Funktionen (für obiges Beispiel sind): *> mindestensEineGrossMutterBekannt "Bruno" False *> mindestensEineGrossMutterBekannt "Dirk" True *> mindestensEineGrossMutterBekannt "Clemens" True *> mindestensEineGrossMutterBekannt "Curt" False *> istVorfahre "Axel" "Dirk" True *> istVorfahre "Axel" "Curt" False *> istVorfahre "Dirk" "Axel" False *> sindGeschwister "Dirk" "Axel" False *> sindGeschwister "Carl" "Clemens" True *> sindGeschwister "Bruno" "Birgit" True *> istCousinOderCousine "Carl" "Clara" True *> istCousinOderCousine "Detlef" "Diana" False *> istCousinOderCousine "Detlef" "Dirk" False *> istCousinOderCousine "Clemens" "Clara" True *> sindVerwandt "Dirk" "Curt" False *> sindVerwandt "Clemens" "Clara" True *> sindVerwandt "Bert" "Dirk" True *> sindVerwandt "Dirk" "Bert" True 2 Aufgabe 2 (15 Punkte) Die Funktionen g1 bis g6 seien in Haskell definiert als: g1 g2 g3 g4 g5 g6 x x x x x x y = = = = = = (g2 (x+10)) * (g3 (x-10)) if x > 100 then 20 else 40 if x <= 0 then 1 else g3 (g4 x) if x == 0 then g3 (x-1) else g6 (x-2) 2 if (g2 (g2 x)) == 20 then g5 (x-20) else 10 if y == 0 then g2 x else g3 (y-10) a) Für welche Funktionen gi, gj (1 ≤ i, j ≤ 6) gilt: Die Funktion gi referenziert Funktion gj direkt? (3 Punkte) b) Für welche Funktionen gi, gj (1 ≤ i, j ≤ 6) gilt: Die Funktion gi referenziert die Funktion gj? (6 Punkte) c) Welche der Funktionen gi mit 1 ≤ i ≤ 6 sind direkt rekursiv? (2 Punkte) d) Welche der Funktionen gi mit 1 ≤ i ≤ 6 sind rekursiv? (2 Punkte) e) Welche Paare (gi, gj) mit 1 ≤ i < j ≤ 6 sind verschränkt rekursiv? (2 Punkte) Aufgabe 3 (40 Punkte) Die Funktion fun sei definert als fun x y = if y <= 3 then x else x*(fun (x-1) (y-2)) definiert. Geben Sie für alle Teilaufgaben jeweils sämtliche Reduktionsschritte sowie die jeweils verwendete Regel als Buchstabe D, A oder I an (D = Definitionseinsetzung, A=Arithmetische Auswertung, I=if-Auswertung). a) Werten Sie fun (fun 3 (2+2)) (10-8) in normaler Reihenfolge aus. (12 Punkte) b) Werten Sie fun (fun (2*5) (3+1)) (2-1) in applikativer Reihenfolge aus. (12 Punkte) c) Werten Sie den Ausdruck fun (2*20) (5-1) in verzögerter Reihenfolge aus. (16 Punkte) Aufgabe 4 (10 Punkte) Die Funktionen g1, g2, g3, g4 und g5 seien in Haskell definiert als: g1 g2 g3 g4 g5 a a a a a b b b b b c c c c c = = = = = if a > b then g1 (a+2) (b-1) c else b if c == 0 then 1 else a + b + g2 (a-1) (b-1) (c-2) if c > 0 then (g3 2 a c) + (g3 (a-b) (b+1) (a-c)) else a+b-(2*c) if c <= 0 then b*a else (g4 (a+c) (b-2) (c-3)) + 10 if b < 0 then True else (g5 6 (b-2) (c*2)) + (g5 (g5 (a-2) (b-4) (c-6)) (4*b) (c-2)) Vervollständigen Sie die folgende Tabelle: . . . ist iterativ . . . ist endrekursiv . . . ist linear rekursiv . . . ist Baum-rekursiv . . . ist geschachtelt Baum-rekursiv g1 ja / ja / ja / ja / ja / g2 ja / ja / ja / ja / ja / nein nein nein nein nein 3 nein nein nein nein nein g3 ja / ja / ja / ja / ja / nein nein nein nein nein g4 ja / ja / ja / ja / ja / nein nein nein nein nein g5 ja / ja / ja / ja / ja / nein nein nein nein nein