Tutoraufgabe 1 (Datenstrukturen in Haskell):

Ähnliche Dokumente
Tutoraufgabe 1 (Datenstrukturen in Haskell):

Tutoraufgabe 1 (Programmanalyse):

Tutoraufgabe 1 (2 3 4 Bäume):

Tutoraufgabe 1 (Vollständige Induktion): Tutoraufgabe 2 (Rotationen): Datenstrukturen und Algorithmen SS15 Übungsblatt 5 (Abgabe 3.6.

Tutoraufgabe 1 (Programmieren in Prolog):

Tutoraufgabe 1 (Programmanalyse):

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell):

Programmieren in Haskell Programmiermethodik

expr :: Expr expr = Mul (Add (Const 3) (Const 4)) (Div (Sub (Const 73) (Const 37)) (Const 6))

Tag 7. Pattern Matching und eigene Datentypen

Beispiele: (Funktionen auf Listen) (3) Bemerkungen: Die Datenstrukturen der Paare (2) Die Datenstrukturen der Paare

Übungen zu Programmierung I - Blatt 8

Probeklausur: Programmierung WS04/05

PIWIN 1 Übung Blatt 5

Übungen zur Vorlesung EidP (WS 2015/16) Blatt 6

Programmierkurs Java

Typdeklarationen. Es gibt in Haskell bereits primitive Typen:

Crashkurs Haskell Mentoring WiSe 2016/17. Anja Wolffgramm Freie Universität Berlin

Frage, Fragen und nochmals Fragen

Assoziative Container in C++ Christian Poulter

Bei for-schleifen muss man nur immer bedenken, dass die letzte Anweisung immer erst nach der Ausführung der restlichen Anweisungen der Schleife

Fakultät Angewandte Informatik Programmierung verteilter Systeme Übungen zur Vorlesung Informatik II, Blatt 6

Funktionale Programmierung mit Haskell

1 Polymorphie (Vielgestaltigkeit)

Tutoraufgabe 1 (Zweierkomplement): Lösung: Programmierung WS16/17 Lösung - Übung 2

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = Euro ergeben.

1. Typen und Literale (6 Punkte) 2. Zuweisungen (6 = Punkte)

Grundlagen Programmierung

Programmieren in Haskell

Tutoren Simon Andermatt Lukas Beck. Alexis Peter Thomas Ritter

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Einige andere Programmiersprachen. Typisierung in Haskell

2.5 Listen. Kurzschreibweise: [42; 0; 16] Listen werden mithilfe von [] und :: konstruiert.

Einführung in die Java- Programmierung

Programmieren in Haskell. Abstrakte Datentypen

Agenda. 1 Einleitung. 2 Binäre Bäume. 3 Binäre Suchbäume. 4 Rose Trees. 5 Zusammenfassung & Ausblick. Haskell Bäume. Einleitung.

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung

Allgemeine Informatik II SS :30-13:30 Uhr

7. Objektorientierte Softwareentwicklung/3. Informatik II für Verkehrsingenieure

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

Javakurs für Anfänger

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6

Suchen. lineare Suche, binäre Suche, divide and conquer, rekursive und iterative Algorithmen, geordnete Daten, Comparable

Tutoren Jan Ebbe Pat Mächler Valentino Rugolo Sascha Scherrer. Grundlagen der Programmierung (CS101) - Blatt 8 Theorie [4 Punkte] - Praxis [12 Punkte]

Übungsblatt 4. Java Vorkurs (WS 2015)

Institut für Programmierung und Reaktive Systeme 25. August Programmier-Labor Übungsblatt. int binarysearch(int[] a, int x),

Einstieg in die Informatik mit Java

Strukturelle Rekursion und Induktion

Technische Universität Braunschweig Institut für Programmierung und Reaktive Systeme

7. Schnittstellen Grundlagen zu Schnittstellen. 7. Schnittstellen

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Kapitel 3: Variablen

Javakurs für Anfänger

Wiederholung ADT Menge Ziel: Verwaltung (Finden, Einfügen, Entfernen) einer Menge von Elementen

Objektorientierte Programmierung Einstufungstest

Vorsicht bei redundanten und unvollständigen Matches!

Übung Datenstrukturen. Objektorientierung in C++

Klausur C-Programmierung / / Klingebiel / 60 Minuten / 60 Punkte

3 Objektorientierte Konzepte in Java

Funktionale Programmierung

Institut für Informatik

Übung 9. Quellcode Strukturieren Rekursive Datenstrukturen Uebung 9

Welche Informatik-Kenntnisse bringen Sie mit?

Binary Decision Diagrams (Einführung)

Inhaltsverzeichnis. Praktikum Algoritmen und Datenstrukturen WS2004/2005 Paul Litzbarski Stefan Nottorf. Druckmanager allgemein 2.

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme

Klausur zur Veranstaltung Programmierung (fortgeschrittene Konzepte)

Allgemeine Hinweise: TECHNISCHE UNIVERSITÄT MÜNCHEN. Name Vorname Studiengang Matrikelnummer. Hörsaal Reihe Sitzplatz Unterschrift

Aufgabenblatt Nr. 5 Generizität und TicTacToe

1. Probeklausur zu Programmierung 1 (WS 07/08)

Fortgeschrittene Programmiertechnik Klausur SS 2015 Angewandte Informatik Bachelor

Funktionale Programmiersprachen

Javakurs für Anfänger

Java 8. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Oktober 2014 JAV8

5. Tutorium zu Programmieren

Grundzüge der Programmierung. Wiederverwendung VERERBUNG

Es ist für die Lösung der Programmieraufgabe nicht nötig, den mathematischen Hintergrund zu verstehen, es kann aber beim Verständnis helfen.

Vorlesung Datenstrukturen

Funktionale Programmierung mit Haskell

Tutoraufgabe 1 (Überladen von Methoden):

Probeklausur: Programmierung WS04/05

Ausdrücke und primitive Typen

Bearbeitungszeit: 120 Minuten. Kommentare kosten Zeit; kommentieren Sie ihr Programm nur da, wo der Code alleine nicht verständlich wäre.

Programmierung mit C Zeiger

WS 2011/2012. Georg Sauthoff 1. November 1, 2011

Softwaretechnik. Funktionale Programmierung. Christian Lindig. 23. Januar Lehrstuhl für Softwaretechnik Universität des Saarlandes

Programmieren Tutorium

Algorithmen & Datenstrukturen 1. Klausur

R-Wörterbuch Ein Anfang... ein Klick auf einen Begriff führt, sofern vorhanden, zu dessen Erklärung.

Programmieren - C++ Funktions-Templates

Funktionale Programmierung ALP I. Funktionen höherer Ordnung. Teil 2 SS Prof. Dr. Margarita Esponda. Prof. Dr.

Java Einführung Methoden in Klassen

Prof. Dr. Heinrich Müller; Dr. Frank Weichert 7. September 2015

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme

Programmierprojekt Aufgabe 1

Java Einführung Klassendefinitionen

Informatik B von Adrian Neumann

Objektorientierte Programmierung

Definieren Sie eine Funktion circlearea zur Berechnung der Fläche eines Kreises mit gegebenen Radius (Float).

5.4 Klassen und Objekte

Typklassen, Eingabe und Monaden In Haskell

Transkript:

Prof. aa Dr. M. Müller Programmierung WS15/16 C. Aschermann, J. Hensel, J. Protze, P. Reble Allgemeine Die Hausaufgaben sollen in Gruppen von je 3 Studierenden aus der gleichen Kleingruppenübung (Tutorium) bearbeitet werden. Namen und Matrikelnummern der Studierenden sind auf jedes Blatt der Abgabe zu schreiben. Heften bzw. tackern Sie die Blätter! Die Nummer der Übungsgruppe muss links oben auf das erste Blatt der Abgabe geschrieben werden. Notieren Sie die Gruppennummer gut sichtbar, damit wir besser sortieren können. Die Lösungen müssen bis Montag, den 01.02.2016 um 15:00 Uhr in den entsprechenden Übungskasten eingeworfen werden. Sie finden die Kästen am Eingang Halifaxstr. des Informatikzentrums (Ahornstr. 55). Alternativ können Sie die Lösungen auch vor der Abgabefrist direkt bei Ihrer Tutorin/Ihrem Tutor abgeben. In einigen Aufgaben müssen Sie in Haskell oder Prolog programmieren und.hs- bzw..pl-dateien anlegen. Drucken Sie diese aus und schicken Sie sie per E-Mail vor Montag, dem 01.02.2016 um 15:00 Uhr an Ihre Tutorin/Ihren Tutor. Stellen Sie sicher, dass Ihr Programm von GHC bzw. SWI akzeptiert wird, ansonsten werden keine Punkte vergeben. Tutoraufgabe 1 (Datenstrukturen in Haskell): In dieser Aufgabe beschäftigen wir uns mit Kindermobiles, die man beispielsweise über das Kinderbett hängen kann. Ein Kindermobile besteht aus mehreren Figuren, die mit Fäden aneinander aufgehängt sind. Als mögliche Figuren im Mobile beschränken wir uns hier auf Sterne, Seepferdchen, Elefanten und Kängurus. An Sternen und Seepferdchen hängt keine weitere Figur. An jedem Elefant hängt eine weitere Figur, unter jedem Känguru hängen zwei Figuren. Weiterhin hat jedes Känguru einen Beutel, in dem sich etwas befinden kann (z. B. eine Zahl). In der folgenden Grafik finden Sie zwei beispielhafte Mobiles 1. 1 Für die Grafik wurden folgende Bilder von Wikimedia Commons verwendet: Stern http://commons.wikimedia.org/wiki/file:crystal_clear_action_bookmark.png Seepferdchen http://commons.wikimedia.org/wiki/file:seahorse.svg Elefant http://commons.wikimedia.org/wiki/file:african_elephant_transparent.png Känguru http://commons.wikimedia.org/wiki/file:kangourou.svg 1

a) Entwerfen Sie einen parametrischen Datentyp Mobile a mit vier Konstruktoren (für Sterne, Seepferdchen, Elefanten und Kängurus), mit dem sich die beschriebenen Mobiles darstellen lassen. Verwenden Sie den Typparameter a dazu, den Typen der Känguru-Beutelinhalte festzulegen. Modellieren Sie dann die beiden oben dargestellten Mobiles als Ausdruck dieses Datentyps in Haskell. Nehmen Sie hierfür an, dass die gezeigten Beutelinhalte vom Typ Int sind. Für Tests der weiteren Teilaufgaben bietet es sich an, die beiden Mobiles als konstante Funktionen im Programm zu deklarieren. Schreiben Sie deriving Show an das Ende Ihrer Datentyp-Deklaration. Damit können Sie sich in GHCi ausgeben lassen, wie ein konkretes Mobile aussieht. mobilelinks :: Mobile Int mobilelinks =... b) Schreiben Sie eine Funktion count :: Mobile a -> Int, die die Anzahl der Figuren im Mobile berechnet. Für die beiden gezeigten Mobiles soll also 8 und 6 zurückgegeben werden. c) Schreiben Sie eine Funktion liste :: Mobile a -> [a], die alle in den Känguru-Beuteln enthaltenen Elemente in einer Liste (mit beliebiger Reihenfolge) zurückgibt. Für das linke Mobile soll also die Liste [1,2,3] (oder eine Permutation davon) berechnet werden. d) Schreiben Sie eine Funktion greife :: Mobile a -> Int -> Mobile a. Diese Funktion soll für den Aufruf greife mobile n die Figur mit Index n im Mobile mobile zurückgeben. Wenn man sich das Mobile als Baumstruktur vorstellt, werden die Indizes entsprechend einer Tiefensuche 2 berechnet: Wir definieren, dass die oberste Figur den Index 1 hat. Wenn ein Elefant den Index n hat, so hat die Nachfolgefigur den Index n + 1. Wenn ein Känguru den Index n hat, so hat die linke Nachfolgefigur den Index n + 1. Wenn entsprechend dieser Regeln alle Figuren im linken Teil-Mobile einen Index haben, hat die rechte Nachfolgefigur den nächsthöheren Index. Im linken Beispiel-Mobile hat das Känguru mit Beutelinhalt 3 also den Index 5. Benutzen Sie die Funktion count aus Aufgabenteil b). Falls der übergebene Index kleiner 1 oder größer der Anzahl der Figuren im Mobile ist, darf sich Ihre Funktion beliebig verhalten. Aufgabe 2 (Datenstrukturen in Haskell): (1 + 1 + 1 + 2 + 2 = 7 Punkte) In dieser Aufgabe betrachten wir eine einfache assoziative Datenstruktur in Form einer Liste. Bei einer assoziativen Datenstruktur ist es möglich, einzelnen Schlüsselwerten jeweils einen Wert zuzuordnen. Beispielsweise kann jedes Telefonbuch als assoziative Datenstruktur verstanden werden, bei der zu jedem Namen (dem Schlüssel) im Buch die dazugehörige Telefonnummer (der Wert) angegeben ist. Wir speichern in dieser Aufgabe die Paare aus Schlüssel und Wert in einer Liste. In der Beispielgrafik erkennt man eine solche Liste, die zum Namen "Meier" die Nummer 908256, zum Namen "Becker" die Nummer 503020 und zum Namen "Schmitz" die Nummer 493827 gespeichert hat. Meier 908256 Becker 503020 Schmitz 493827 Verwenden Sie in dieser Aufgabe keine vordefinierten Listen oder Tupel! 2 siehe auch Wikipedia: http://de.wikipedia.org/wiki/tiefensuche 2

a) Entwerfen Sie einen parametrisierten Datentyp AList value, mit dem assoziative Listen über Schlüssel vom Datentyp String und Werte vom Datentyp value dargestellt werden können. Für die nachfolgenden Aufgaben ist es sehr hilfreich, die obige Beispielliste unter dem Namen bsp zur Verfügung zu haben: bsp :: AList Int bsp =... Ergänzen Sie deriving Show am Ende der Datenstruktur, damit GHCi die Listen auf der Konsole anzeigen kann: data... deriving Show b) Schreiben Sie die Funktion size, die eine assoziative Liste vom Typ AList a übergeben bekommt und als Rückgabe die Anzahl der Einträge in dieser Liste (also die Länge der Liste) als Int zurückgibt. Für die Beispielliste (angenommen diese ist als bsp verfügbar) soll für den Aufruf size bsp also 3 zurückgegeben werden. c) Schreiben Sie die Funktion contained. Diese bekommt als erstes Argument eine assoziative Liste vom Typ AList a und als zweites Argument einen String. Der Rückgabewert dieser Methode ist vom Typ Bool. Die Methode gibt True zurück, wenn in der Liste ein Element enthalten ist, das als Schlüssel den String des zweiten Arguments hat. Ansonsten wird False zurückgegeben. Für die Beispielliste bsp soll der Aufruf contained bsp "Becker" also True zurückgeben, contained bsp "Meyer" gibt False. d) Schreiben Sie die Funktion put. Diese bekommt als erstes Argument eine assoziative Liste vom Typ AList a, als zweites Argument einen String und als drittes Argument einen Wert vom Typ a. Der Rückgabewert der Funktion ist die wie folgt modifizierte assoziative Liste vom Typ AList a: Falls für den im zweiten Argument übergebenen Schlüssel bereits ein Element in der Liste existiert, wird dessen Wert mit dem im dritten Argument übergebenen Wert überschrieben. Falls kein solches Element existiert, wird dieses hinzugefügt. Gehen Sie hierbei davon aus, dass zu jedem Schlüssel in der Liste auch nur genau ein Listenelement existiert. Für die Beispielliste bsp soll der Aufruf put bsp "Becker" 1 also die assoziative Liste zurückgeben, bei der statt 503020 nun 1 für den Schlüssel "Becker" gespeichert ist. e) Schreiben Sie, analog zu map, die Funktion mapalist. Diese bekommt als erstes Argument eine Funktion vom Typ a -> b und als zweites Argument eine assoziative Liste vom Typ AList a. Der Rückgabewert der Funktion ist die wie folgt definierte assoziative Liste vom Typ AList b: Für jedes Paar (x, y) in der Eingabeliste (des zweiten Arguments) enthält die Ergebnisliste ein Paar (x, z). Wenn f die Funktion des ersten Arguments ist, ist z das Ergebnis von f y. Die Ergebnisliste enthält keine weiteren Paare. Für die Beispielliste bsp soll der Aufruf mapalist (* (-1)) bsp also die assoziative Liste zurückgeben, bei der Elemente für die Paare (Meier, -908256), (Becker, -503020) und (Schmitz, -493827) vorhanden sind. Tutoraufgabe 3 (Typen in Haskell): Bestimmen Sie zu den folgenden Haskell-Funktionen f, g, h und i den jeweils allgemeinsten Typ. Geben Sie den Typ an und begründen Sie Ihre Antwort. Gehen Sie hierbei davon aus, dass alle Zahlen den Typ Int haben und die Funktion + den Typ Int -> Int -> Int hat. i) f [] x y = y f [z:zs] x y = f [] (z:x) y 3

ii) g x 1 = 1 g x y = (\x -> (g x 0)) y iii) data T a b = C0 C1 a C2 b C3 ( T a b) ( T a b) i (C3 (C1 []) (C2 y)) = C1 0 i (C3 (C2 []) (C1 y)) = C2 0 i (C3 (C1 (x:xs )) (C2 y)) = i (C3 (C1 y) (C2 [x ])) Versuchen Sie, diese Aufgabe ohne Einsatz eines Rechners zu lösen. Bedenken Sie, dass Sie in einer Prüfung ebenfalls keinen Rechner zur Verfügung haben. Aufgabe 4 (Typen in Haskell): (1 + 1 + 2 + 3 = 7 Punkte) Bestimmen Sie zu den folgenden Haskell-Funktionen f, g, h und i den jeweils allgemeinsten Typ. Geben Sie den Typ an und begründen Sie Ihre Antwort. Gehen Sie hierbei davon aus, dass alle Zahlen den Typ Int haben und die Funktionen +, head und == die Typen Int -> Int -> Int, [a] -> a und a -> a -> Bool haben. i) f ( x : xs) y z = x + y f xs y z = if xs == z then y else head xs + y ii) g [] = g [1] g x = (\x -> x) x iii) h w x [] z = if z == [ x] then w else h w x [] z h w x y z = if x then head y else ( x, x) iv) data N a b = A a F ( a - > b) I Int i (F f) x = f x i (A y) x = i k x where k = F (\x -> I y) Versuchen Sie, diese Aufgabe ohne Einsatz eines Rechners zu lösen. Bedenken Sie, dass Sie in einer Prüfung ebenfalls keinen Rechner zur Verfügung haben. Tutoraufgabe 5 (Higher Order): Wir betrachten Operationen auf dem Typ Tree, der (mit einem Testwert) wie folgt definiert ist: data Tree = Node Int Tree Tree deriving Show testtree = Node 2 ( Node 4 ( Node 9 ) ( Node 3 ( Node 7 ))) ( Node 17 ) Man kann den Baum auch graphisch darstellen: 4

2 4 17 9 3 7 Wir wollen nun eine Reihe von Funktionen betrachten, die auf diesen Bäumen arbeiten: dectree :: Tree - > Tree dectree = dectree ( Node v l r) = Node (v - 1) ( dectree l) ( dectree r) sumtree :: Tree - > Int sumtree = 0 sumtree ( Node v l r) = v + ( sumtree l) + ( sumtree r) flattentree :: Tree - > [ Int ] flattentree = [] flattentree ( Node v l r) = v : ( flattentree l) ++ ( flattentree r) Wir sehen, dass diese Funktionen alle in der gleichen Weise konstruiert werden: Was die Funktion mit einem Baum macht, wird anhand des verwendeten Datenkonstruktors entschieden. Der nullstellige Konstruktor wird einfach in einen Standard-Wert übersetzt. Für den dreistelligen Konstruktor Node wird die jeweilige Funktion rekursiv auf den Kindern aufgerufen und die Ergebnisse werden dann weiterverwendet, z.b. um ein neues Tree-Objekt zu konstruieren oder ein akkumuliertes Gesamtergebnis zu berechnen. Intuitiv kann man sich vorstellen, dass jeder Konstruktor durch eine Funktion der gleichen Stelligkeit ersetzt wird. Klarer wird dies, wenn man die folgenden alternativen Definitionen der Funktionen von oben betrachtet: dectree = dectree ( Node v l r) = decn v ( dectree l) ( dectree r) decn = \ v l r - > Node ( v - 1) l r sumtree = 0 sumtree ( Node v l r) = sumn v ( sumtree l) ( sumtree r) sumn = \ v l r - > v + l + r flattentree = [] flattentree ( Node v l r) = flattenn v ( flattentree l) ( flattentree r) flattenn = \ v l r - > v : l ++ r Die definierenden Gleichungen für den Fall, dass der betrachtete Baum durch den Konstruktor Node erzeugt wird, kann man in allen diesen Definitionen so lesen, dass die eigentliche Funktion rekursiv auf die Kinder angewandt wird und der Konstruktor Node durch die jeweils passende Hilfsfunktion (decn, sumn, flattenn) ersetzt wird. Der Konstruktor wird analog durch eine nullstellige Funktion (also eine Konstante) ersetzt. Als Beispiel kann der Ausdruck dectree testtree dienen, der dem folgenden Ausdruck entspricht: decn 2 ( decn 4 ( decn 9 ) ( decn 3 ( decn 7 ))) ( decn 17 ) 5

Im Baum testtree sind also alle Vorkommen von Node durch decn und alle Vorkommen von durch ersetzt worden. Analog ist sumtree testtree äquivalent zu sumn 2 ( sumn 4 ( sumn 9 0 0) ( sumn 3 0 ( sumn 7 0 0))) ( sumn 17 0 0) Im Baum testtree sind also alle Vorkommen von Node durch sumn und alle Vorkommen von durch 0 ersetzt worden. Die Form der Funktionsanwendung bleibt also gleich, nur die Ersetzung der Konstruktoren durch Hilfsfunktionen muss gewählt werden. Dieses allgemeine Muster wird durch die Funktion foldtree beschrieben: foldtree :: ( Int -> a -> a -> a) -> a -> Tree -> a foldtree f c = c foldtree f c ( Node v l r) = f v ( foldtree f c l) ( foldtree f c r) Bei der Anwendung ersetzt foldtree alle Vorkommen des Konstruktors Node also durch die Funktion f und alle Vorkommen des Konstruktors durch die Konstante c. Unsere Funktionen von oben können dann vereinfacht dargestellt werden: dectree t = foldtree decn t sumtree t = foldtree sumn 0 t flattentree t = foldtree flattenn [] t a) Implementieren Sie eine Funktion prodtree, die das Produkt der Einträge eines Baumes bildet. Es soll also prodtree testtree = 2 * 4 * 9 * 3 * 7 * 17 = 25704 gelten. Verwenden Sie dazu die Funktion foldtree. b) Implementieren Sie eine Funktion inctree, die einen Baum zurückgibt, in dem der Wert jeden Knotens um 1 inkrementiert wurde. Verwenden Sie dazu die Funktion foldtree. Aufgabe 6 (Higher Order): (1 + 0.5 + 2.5 + 2 = 6 Punkte) Wir betrachten Operationen auf dem parametrisierten Typ List, der (mit zwei Testwerten) wie folgt definiert ist: data List a = Cons a ( List a) deriving Show testlist, testlist2 :: List Int testlist = Cons ( -23) ( Cons 42 ( Cons 19 ( Cons ( -38) ))) testlist2 = Cons 1 ( Cons 2 ) Die Liste testlist entspricht also 23, 42, 19, 38 und testlist2 der Liste 1, 2. a) Schreiben Sie eine Funktion filterlist :: (a -> Bool) -> List a -> List a, die sich auf unseren selbstdefinierten Listen wie filter auf den vordefinierten Listen verhält. Es soll also die als erster Parameter übergebene Funktion auf jedes Element angewandt werden um zu entscheiden, ob dieses auch im Ergebnis auftaucht. Der Ausdruck filterlist (\x -> x > 30 x < -30) testlist soll dann also zu (Cons 42 (Cons -38 )) auswerten. b) Schreiben Sie eine Funktion poslist :: List Int -> List Int, die die Teilliste der positiven Werte zurückgibt. Für testlist soll also Cons 42 (Cons 19 ) zurückgegeben werden. Verwenden Sie dafür filterlist. c) Schreiben Sie eine Funktion foldlist :: (a -> b -> b) -> b -> List a -> b, die wie foldtree aus der vorhergegangen Tutoraufgabe die Datenkonstruktoren durch die übergebenen Argumente ersetzt. Der Ausdruck foldlist f c (Cons x 1 (Cons x 2... (Cons x n )... ) soll dann also äquivalent zu (f x 1 (f x 2... (f x n c)... ) sein. Beispielsweise soll für times x y = x * y der Ausdruck foldlist times 1 testlist zu -23 * 42 * 19 * -38 = 697452 ausgewertet werden. 6

d) Implementieren Sie die Funktion filterlist unter dem Namen filterlist erneut, verwenden Sie diesmal aber foldlist, statt direkt Rekursion in der Definition von filterlist zu verwenden. Tutoraufgabe 7 (Programmieren in Prolog): In dieser Aufgabe sollen einige Abhängigkeiten im Übungsbetrieb Programmierung in Prolog modelliert und analysiert werden. Die gewählten Personennamen sind frei erfunden und eventuelle Übereinstimmungen mit tatsächlichen Personennamen sind purer Zufall. Person Rang M. Müller (mmu) Professor C. Aschermann (cas) Assistent J. Hensel (jhe) Assistent J. Protze (jpr) Assistent P. Reble (pre) Assistent S. Bender (sbe) Tutor I. Klöter (ikl) Tutor F. Ail (fai) Student N. Erd (ner) Student M. Ustermann (mus) Student Schreiben Sie keine Prädikate außer den geforderten und nutzen Sie bei Ihrer Implementierung jeweils Prädikate aus den vorangegangenen Aufgabenteilen. a) Übertragen Sie die Informationen der Tabelle in eine Wissensbasis für Prolog. Geben Sie hierzu Fakten für die Prädikatssymbole person und hatrang an. Hierbei gilt person(x), falls X eine Person ist und hatrang(x, Y), falls X den Rang Y hat. b) Stellen Sie eine Anfrage an das im ersten Aufgabenteil erstellte Programm, mit der man herausfinden kann, wer ein Assistent ist. Durch die wiederholte Eingabe von ; nach der ersten Antwort werden alle Antworten ausgegeben. c) Schreiben Sie ein Prädikat bossvon, womit Sie abfragen können, wer innerhalb der Übungsbetriebshierarchie einen Rang direkt über dem eines anderen bekleidet. Die Reihenfolge der Ränge ist Professor > Assistent > Tutor > Student. So ist z.b. bossvon(cas,sbe) wahr, während bossvon(pre,fai) und bossvon(sbe,cas) beide falsch sind. d) Schreiben Sie nun ein Prädikat hatgleichenrang mit einer Regel (ohne neue Fakten), mit dem Sie alle Paare von Personen abfragen können, die den gleichen Rang innerhalb des Übungsbetriebs bekleiden. So ist z.b. hatgleichenrang(jpr, jhe) wahr, während hatgleichenrang(ikl, mmu) falsch ist. Stellen Sie sicher, dass hatgleichenrang(x, Y) nur dann gilt, wenn X und Y Personen sind. e) Schreiben Sie schließlich ein Prädikat vorgesetzt mit zwei Regeln (wieder ohne neue Fakten), mit dem Sie alle Paare von Personen abfragen können, sodass die erste Person in der Übungsbetriebshierarchie der zweiten Person vorgesetzt ist. Eine Person X ist einer Person Y vorgesetzt, wenn der Rang von X größer als der Rang von Y ist (wobei wieder Professor > Assistent > Tutor > Student gilt). So sind z.b. vorgesetzt(pre, sbe) und vorgesetzt(cas, fai) beide wahr, während vorgesetzt(sbe, pre) falsch ist. Stellen Sie auch hier sicher, dass vorgesetzt(x, Y) nur dann gilt, wenn X und Y Personen sind. 7

Aufgabe 8 (Programmieren in Prolog): Wir betrachten die Java-Klassenhierarchie aus Übung 9: (2 + 1 + 2 = 5 Punkte) «abstract» Baumaschine - double motorleistung Bagger - int anzahlgrabwerkzeuge Schaufelradbagger - double raddurchmesser Seilbagger - double seillaenge «abstract» Transportgeraet Foerderband - double bandbreite Kipplaster - double kippwinkel «interface» Fahrzeug + double getmaxgeschwindigkeit() a) Übertragen Sie die Klassenhierarchie in eine Wissensbasis für Prolog. Beschränken Sie sich hierbei auf die Namen der Klassen und des Interfaces. Verwenden Sie die zweistelligen Prädikate extends und implements, so dass extends(a, B) gilt wenn die Klasse A (direkt) die Klasse B erweitert (also A extends B im Quellcode stehen würde). Die Bedeutung von implements ist analog zu verstehen. b) Schreiben Sie eine Anfrage, die alle Klassen als Antwort zurückgibt, die die Klasse Transportgeraet direkt erweitern. c) Schreiben Sie das zweistellige Prädikat instanceof. Der Aufruf instanceof(a, B) soll wahr sein, wenn A und B identisch sind, oder A eine Klasse bzw. Interface M direkt erweitert/implementiert und instanceof(m, B) gilt 8