Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zur Übungsklausur -

Ähnliche Dokumente
Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zu Übung 4 -

Programmieren in Haskell Programmiermethodik

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

ProInformatik: Funktionale Programmierung. Punkte

Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zu Übung 9 -

Programmieren in Haskell Einstieg in Haskell

Programmieren in Haskell

Paradigmen der Programmierung

Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zu Übung 8 -

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

Einführung in die funktionale Programmierung

Programmieren in Haskell

Programmieren in Haskell

Einführung in die Informatik 2

Programmieren in Haskell. Stefan Janssen. Strukturelle Rekursion. Universität Bielefeld AG Praktische Informatik. 10.

Einführung in die Informatik 2

HASKELL KAPITEL 2.1. Notationen: Currying und das Lambda-Kalkül

Grundlegende Datentypen

Prüfung Funktionale Programmierung

Übung Algorithmen und Datenstrukturen

4.1 Bäume, Datenstrukturen und Algorithmen. Zunächst führen wir Graphen ein. Die einfachste Vorstellung ist, dass ein Graph gegeben ist als

Funktionale Programmierung mit Haskell

Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom : Typvariablen und Polymorphie

Grundlegende Datentypen

Gliederung. Algorithmen und Datenstrukturen I. Listen in Haskell: Listen in Haskell: Listen in Haskell. Datentyp Liste Strings Listenkomprehension

Ströme als unendliche Listen in Haskell

Typ-Polymorphismus. November 12, 2014

Die Korrektheit von Mergesort

Funktionale Programmierung Grundlegende Datentypen

Praktische Informatik 3: Funktionale Programmierung Vorlesung 6 vom : Funktionen Höherer Ordnung II und Effizienzaspekte

Workshop Einführung in die Sprache Haskell

Teillösung zum 7.Aufgabenblatt zur Vorlesung Informatik A

Prof. Dr. Margarita Esponda

Was bisher geschah Funktionale Programmierung in Haskell: Algebraische Datentypen Pattern Matching Polymorphie Typklassen Rekursive Datentypen:

Einführung in die Informatik 2

Frage, Fragen und nochmals Fragen

Lösungsvorschläge zu: Eine Einführung in die funktionale Programmierung mit Haskell

Funktionen höherer Ordnung

Prüfung Funktionale Programmierung

Funktionale Programmierung ALP I. Algebraische Datentypen und Abstrakte Datentypen. SS 2013 Prof. Dr. Margarita Esponda. Prof. Dr.

ALP I. Funktionale Programmierung

Programmieren in Haskell Das Haskell Typsystem

Programmieren in Haskell

INFORMATIK FÜR BIOLOGEN

Kapitel 3: Eine einfache Programmiersprache. Programmieren in Haskell 1

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

Musterlösung zur 2. Aufgabe der 4. Übung

13 Berechenbarkeit und Aufwandsabschätzung

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen, Bäume)

Funktionale Programmierung Mehr funktionale Muster

1 - FortProg ist: [ ] objekt-orientiert; [ ] funktional; [ ] logisch; [ ] manchmal nicht auszuhalten

Grundlegende Datentypen

Programmierung WS18/19 Übungsblatt 9 (Abgabe Freitag, den um 12 Uhr)

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

WS 2011/2012. Robert Giegerich Dezember 2013

ALP I. Funktionale Programmierung

Einführung in Haskell

WS 2012/2013. Robert Giegerich. 21. November 2012

Programmieren in Haskell

Funktionale Programmierung

Typklassen. Natascha Widder

WS 2011/2012. RobertGiegerich. November 12, 2013

Funktionale Programmierung. ALP I Lambda-Kalkül. Teil III SS Prof. Dr. Margarita Esponda. Prof. Dr. Margarita Esponda

WS 2011/2012. RobertGiegerich. November 12, 2013

Crashkurs: Haskell. Mentoring FU Berlin Felix Droop

Praktische Informatik 3: Funktionale Programmierung Vorlesung 5 vom : Funktionen Höherer Ordnung I

Informatik A WS 2007/08. Nachklausur

Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zu Übung 3 -

Lösung: InfA - Übungsblatt 07

Programmierkurs II. Typsynonyme & algebraische Datentypen

Programmieren in Haskell Abstrakte Datentypen

Klausur Programmierung WS 2002/03

Theorembeweiserpraktikum SS 2016

Grundlagen der Programmierung 3 A

Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom : Typvariablen und Polymorphie

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

Einführung in die Informatik 2

Grundlagen der Programmierung 2. Unendliche Listen und Ströme(B)

Algorithmen und Datenstrukturen I

ALP I. Funktionale Programmierung

Grundlagen der Programmierung 3 A

Monoide. Funktionale Programmierung. Prof. Dr. Oliver Braun Letzte Änderung: :54. Monoide 1/16

ALP I Induktion und Rekursion

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Überladung und Konversion in Haskell. Typisierung in Haskell

WS 2011/2012. Robert Giegerich. October 30, 2013

Funktionale Programmierung. Monoide. Prof. Dr. Oliver Braun. Fakultät für Informatik und Mathematik Hochschule München

Probeklausur zur Vorlesung

9 Algebraische Datentypen

Haskell Seminar Abstrakte Datentypen. Nils Bardenhagen ms2725

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

WS 2013/2014. Robert Giegerich. 11. Dezember 2013

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

Unendliche Listen und Bäume

Haskell for Hackers... or why functional programming matters

Abstrakter Datentyp (ADT): Besteht aus einer Menge von Objekten, sowie Operationen, die auf diesen Objekten wirken.

Kapitel 6: Abstraktion. Programmieren in Haskell 1

Motivation Von Funktoren, Komposition, Applikation Zu Monoiden Die Monade Zusammenfassung. Monaden für alle. Franz Pletz

Praktische Informatik 3: Funktionale Programmierung Vorlesung 5 vom : Funktionen Höherer Ordnung I

Transkript:

Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zur Übungsklausur - Punkte: A1: 30, A2: 20, A3: 20, A4: 20, A5: 10, A6: 20 Punkte: /120 12.02.2012 Hinweis: Geben Sie bei allen verwendeten Funktionen die Signaturen an. Viel Erfolg! 1 Haskell-la-vista! (10+10+10=30 Punkte) 1.1 Funktionen höherer Ordnung (10 Teilpunkte) Schreiben Sie unter Verwendung der map und foldr Funktionen eine Funktion sumquad, die bei Eingabe eines ganzzahligen positiven Werts n, die Summe aller Quadratzahlen von 1 bis n berechnet. sumquad :: Integer -> Integer sumquad n (n >= 0) = foldr (+) 0 (map (^2) [1..n]) otherwise = error "wrong input!" 1

1.2 Klassen + Instanzen (10 Teilpunkte) Seien zwei verschiedene algebraische Datentypen, einer für die Darstellung der natürlichen Zahlen (N) und einer für die Darstellung der ganzen Zahlen (Z) gegeben: data N = Zero S (N) deriving (Show) data Z = Z (N,N) deriving (Show) Erklärung: Wenn a die Zahl x darstellt und b die Zahl y darstellt, dann stellt Z (a,b) die Zahl x y dar. Beispiele: Mit dem Datentyp N kann man Zahlen wie folgt darstellen: 3 = S(S(S(Zero))) 7 = S(S(S(S(S(S(S(Zero))))))) Mit dem Datentyp Z kann man Zahlen wie folgt darstellen: 3 = ( S(S(S(Zero))), Zero ) 3 = ( S(S(S(S(Zero)))), S(Zero) ) -2 = ( Zero, S(S(Zero)) ) -2 = ( S(S(Zero)), S(S(S(S(Zero)))) ) Schreiben Sie die Typ-Klasse Rechnen, die Ihnen die Operation Addition bereitstellt und implementieren Sie jeweils eine Instanz für jeden algebraischen Datentypen. class Rechnen a add::a -> a -> a instance Rechnen N add::n -> N -> N add Zero y = y add S(x) y = add x S(y) instance Rechnen Z add::z -> Z -> Z add (Z (a,b)) (Z (x,y)) = Z ((add a x),(add b y)) 2

1.3 Typ-Inferenz (10 Teilpunkte) Es seien folgende Funktionssignaturen bekannt. map :: (a -> b) -> [a] -> [b] sum :: (Num a) => [a] -> a length :: [a] -> Int show :: (Show a) => a -> String Bestimmen Sie den Typ der Funktionen: f = sum. map sum g = map (show. length) f :: (Num a) => [[a]] -> a Erklärung zu f: 01) map hat den Typ (a -> b) -> [a] -> [b] 02) sum hat den Typ Num c => [c] -> c 03) sum hat den Typ Num d => [d] -> d 04) sum hat den Typ a -> b, weil es das erste Argument von map ist 05) a = Num d => [d], wegen 03) und 04) 06) b = Num d => d, wegen 03) und 04) 07) x hat den Typ [a] = 05) Num d => [[d]], weil es das zweite Argument von map ist 08) (map length x) hat den Typ [b] = 06) Num d => [d], wegen 01) 09) (map length x) hat den Typ Num c => [c], weil es das erste Argument von sum ist 10) c = d, wegen 08) und 09) 11) sum (map length x) hat den Typ Num d => d, wegen 02) und 10) Aus 07) und 11) folgt, dass (sum. map length) den Typ Num d => [[d]] -> d hat. g :: [[a]] -> [String] Um den Typ von map (show. length) zu bestimmen, schauen wir zuerst, was der Typ von show. length ist. Nach Denition von (.) gilt: (show. length) x = show (length x) Erklärung zu g: 01) show hat den Typ Show a => a -> String 02) length hat den Typ [b] -> Int 03) x hat den Typ [b], weil es das erste Argument von length ist 04) (length x) hat den Typ Int, wegen 02) 05) (length x) hat den Typ Show a => a, weil es das erste Argument von show ist 06) show (length x) hat den Typ String, wegen 01) 07) (show. length) hat den Typ [b] -> String, wegen 03) und 06) Nun können wir den Typ von map (show. length) bestimmen: 08) map hat den Typ (c -> d) -> [c] -> [d] 09) (show. length) hat den Typ c -> d, weil es das erste Argument von map ist 10) c = [b], wegen 07) und 09) 11) d = String, wegen 07) und 09) Aus 08), 10) und 11) folgt, dass map (show. length) den Typ [[b]] -> [String] hat. 3

2 Datenbank (20 Punkte) Schreiben Sie ein Modul SimpleDB, das einen algebraischen Datentyp Datenbank verwendet um eine einfache Datenbank zu simulieren. Eine Datenbank ist eine Liste von 2-Tupeln. Jedes dieser 2- Tupel hat die Form: (key, [value 1, value 2,..., value n ]), wobei n 1 und jeder Schlüssel einzigartig sein muss (Primärschlüssel). Überlegen Sie sich geeignete Typklassen für die Typen der Schlüssel und der Werte. Es sollen folgende Funktionen implementiert werden: create Erzeugt eine leere Datenbank. Der Rückgabewert ist eine Datenbank. select db key Diese Funktion gibt alle Wert zurück, die einem Schlüssel in einer Datenbank zugeordnet sind. Falls der Schlüssel nicht existiert wird eine leere Liste ausgegeben. Falls der Schlüssel existiert wird eine Liste mit allen Werten, die diesem Schlüssel zugeordnet sind, zurückgegeben. Der Rückgabewert ist eine Liste von Werten. update db key value Diese Funktion fügt einer Datenbank einen Schlüsseleintrag mit zugeordnetem Wert hinzu. Falls der Schlüssel existiert und der Wert noch nicht dem Schlüssel zugeordnet ist, wird der Wert dem Schlüssel zugeordnet. Falls der Schlüssel existiert und der Wert bereits dem Schlüssel zugeordnet ist, wird nichts verändert. Falls der Schlüssel nicht existiert wird dieser erzeugt und der Wert diesem zugeordnet. Der Rückgabewert ist eine Datenbank. drop db key value Diese Funktion löscht aus einer Datenbank einen Wert, der einem Schlüssel zugeordnet war. Falls der Schlüssel oder der Wert nicht existiert wird ein Fehler ausgegeben. Falls der Schlüssel existiert wird der Wert aus der Zuordnung zum Schlüssel entfernt. Falls der Schlüssel existiert und nur noch der angegebene Wert als einziger Wert dem Schlüssel zugeordnet ist, wird der Schlüssel ebenfalls aus der Datenbank entfernt. Der Rückgabewert ist eine Datenbank. Tipp: Hilfreiche Funktionen sind elem, takewhile, dropwhile und filter. 4

module SimpleDB (Datenbank, create, select, update, drop) -- Dieses Modul stellt eine ganz einfache Datenbank dar. data (Eq k, Eq v) => Datenbank k v = DB [(k,[v])] deriving (Show) create :: (Eq k, Eq v) => Datenbank k v select :: (Eq k, Eq v) => Datenbank k v -> k -> [v] update :: (Eq k, Eq v) => Datenbank k v -> k -> [v] -> Datenbank k v drop :: (Eq k, Eq v) => Datenbank k v -> k -> [v] -> Datenbank k v create = DB [] select (DB []) _ = [] select (DB ((key', values'):xs)) key (key' == key) = values' otherwise = select (DB xs) key update (DB xs) key values (iselement (DB xs) key) == False = error "Key existiert nicht!" otherwise = (DB (lokey ++ [(key, values)] ++ rokey)) lokey = (takewhile (\x -> (fst x) /= key) xs) rokey = (tail ((dropwhile (\x -> (fst x) /= key)) xs)) drop (DB xs) key values (iselement (DB xs) key) == False = error "Key existiert nicht!" otherwise = (DB (lokey ++ rokey)) lokey = (takewhile (\x -> (fst x) /= key) xs) rokey = (tail ((dropwhile (\x -> (fst x) /= key)) xs)) -- Diese Funktion kann nach dem Import des Moduls nicht direkt aufgerufen werden. -- Scope = private, da iselement nicht in der Exportliste aufgeführt ist. iselement :: (Eq k, Eq v) => Datenbank k v -> k -> Bool iselement (DB []) _ = False iselement (DB ((key',_):xs)) key = (key' == key) iselement (DB xs) key Eine andere nden Sie auf der Veranstaltungsseite. 5

3 Sortieren und Laufzeit (10+10=20 Punkte) 3.1 Sortieren durch Einfügen (10 Teilpunkte) Implementieren Sie den Insertion-Sort-Algorithmus. isort :: [Integer] -> [Integer] isort [] = [] isort (x:xs) = ins x (isort xs) ins :: Integer -> [Integer] -> [Integer] ins x [] = [x] ins x (y:ys) (x <= y) = (x:y:ys) otherwise = y:(ins x ys) 3.2 Laufzeit (10 Teilpunkte) Bestimmen Sie die Laufzeit Ihrer Implementierung. Es reicht wenn Sie die Laufzeit in O-Notation angeben und diese textuell begründen. Die Funktion isort hat eine Laufzeit von O(n 2 ). isort besteht aus zwei Teilen. Der erste Teil durchläuft alle Elemente der Liste, also n Elemente. Bei jedem Durchlauf wird der zweite Teil aufgerufen. Im zweiten Teil wird jedes Element mit dem Kopf der Restliste verglichen und sortiert eingefügt. Der zweite Teil vergleicht (n 1) Elemente miteinander. Zusammen ergibt das eine Laufzeit von n (n 1) = n 2 n O(n 2 ). 6

4 Strukturelle Induktion (10+10=20 Punkte) 4.1 Bäume (10 Teilpunkte) Sei folgender algebraischer Datentyp und folgende Gleichungen gegeben: data Baum = Blatt Int Knoten Baum Baum deriving (Show) -- wendet die Funktion f auf jedes Element des Baumes an maptree :: (Int -> Int) -> Baum -> Baum maptree f (Blatt x) = Blatt (f x) -- mapt.1 maptree f (Knoten lb rb) = Knoten (maptree f lb) (maptree f rb) -- mapt.2 Beweisen Sie mit struktureller Induktion folgende Behauptung: maptree id baum = id baum Es folgt ein Beweis mit struktureller Induktion über (die Tiefe des Baumes) t. zu zeigen: maptree id baum = id baum Induktionsbasis: t = 0, Baum = Blatt x maptree id Baum[t=0] d.h. maptree id (Blatt x) = id (Blatt x) <==> (Blatt (id x)) = id (Blatt x) -- mapt.1 <==> (Blatt x) = (Blatt x) Induktionsvoraussetzung: Sei die Behauptung wahr für alle DT vom Typ Baum der Tiefe t <= n. Induktionsbehauptung: Die Behauptung ist wahr für alle DT vom Typ Baum der Tiefe t <= n+1. Induktionsschritt: n -> n+1 maptree id Baum[t<=(n+1)] d.h. maptree id (Knoten lb rb) = id (Knoten lb rb) -- mapt.2 <==> (Knoten (maptree id lb) (maptree id rb)) = id (Knoten lb rb) -- nach IV <==> (Knoten (id lb) (id rb)) = id (Knoten lb rb) <==> (Knoten (lb) (rb)) = (Knoten lb rb) Es wurde mit struktureller Induktion gezeigt, dass die Behauptung gilt. 7

4.2 Listen (10 Teilpunkte) Seien folgende Gleichungen gegeben: ++.1 : [] ++ ys = ys ++.2 : (x:xs) ++ ys = x:(xs ++ ys) rev.1 : reverse [] = [] rev.2 : reverse (x:xs) = reverse xs ++ [x] rev.3 : reverse (xs ++ ys) = (reverse ys) ++ (reverse xs) Beweisen Sie mit struktureller Induktion folgende Behauptung: reverse (reverse xs) = xs Es folgt ein Beweis mit struktureller Induktion. Induktionsbasis: xs = [] reverse (reverse []) = [] rev.1 <==> reverse [] = [] rev.1 <==> [] = [] Induktionsvoraussetzung: Für eine Liste xs mit beliebiger, aber fester Länge gilt: reverse (reverse xs) = xs Induktionsbehauptung: Dann gilt auch: reverse (reverse (x:xs)) = (x:xs) Induktionsschritt: xs -> (x:xs) reverse (reverse (x:xs)) = (x:xs) rev.2 <==> reverse (reverse xs ++ [x]) = (x:xs) rev.3 <==> reverse [x] ++ reverse (reverse xs) = (x:xs) <==> reverse (x:[]) ++ reverse (reverse xs) = (x:xs) rev.2 <==> (reverse [] ++ [x]) ++ reverse (reverse xs) = (x:xs) rev.1 <==> ([] ++ [x]) ++ reverse (reverse xs) = (x:xs) ++.1 <==> [x] ++ reverse (reverse xs) = (x:xs) nach IV <==> [x] ++ xs = (x:xs) <==> x:[] ++ xs = (x:xs) ++.2 <==> x:([] ++ xs) = (x:xs) ++.1 <==> (x:xs) = (x:xs) Es wurde mit struktureller Induktion gezeigt, dass die Behauptung gilt. 8

5 Primitive Rekursion (10 Punkte) Rekursionsschema: R(0, x 1,..., x m ) = g(x 1,..., x m ) R(S(n), x 1,..., x m ) = h(r(n, x 1,..., x m ), n, x 1,..., x m ) Zeigen Sie, dass die Funktion isodd (Ein Prädikat, das prüft ob eine Zahl ungerade ist. Das Ergebnis ist 1 wenn die Zahl ungerade ist und 0 sonst.) primitiv-rekursiv ist. Sie dürfen nur die Grundfunktionen S und Z voraussetzen, das heiÿt, alle Funktion die Sie ansonsten für Ihren Beweis verwenden müssen Sie ebenfalls beweisen. not 0 = one not n = Z (not (n-1)) one = S Z isodd 0 = Z isodd n = not (isodd (n-1)) 6 λ - Kalkül (5+5+10=20 Punkte) 6.1 Freie und gebundene Ausdrücke (5 Teilpunkte) Bestimmen Sie die freien und gebundenen Variablen im folgenden Ausdruck und geben Sie diese explizit an. Benennen Sie die gebundenen Variablen so um, dass in jedem Ausdruck alle λ- Abstraktionen verschiedene Variablen binden. (λab.(λab.(λc.(λab.abc))ab(cc))(λab.a)(λac.c(c(a)))) (λab.(λde.(λc.(λfg.fgc))de(xx))(λhi.h)(λjk.k(k(j)))) Gebundene Variablen: a, b, c, d, e, f, g, h, i, j, k Freie Variablen: x 9

6.2 λ - Ausdruck reduzieren (5 Teilpunkte) (λa.a(λab.b)(λa.a(λab.b)(λab.a))(λab.b))(λab.ab) Es gibt 2 Möglichkeiten das Problem zu lösen: Elegante : Normale : Z 1 F {}}{{}}{{}}{ (λa.a (λab.b) (λa.a(λab.b)(λab.a)) (λab.b)) (λab.ab) = (λab.b) }{{}}{{}}{{} F F (λa.a(λab.b)(λa.a(λab.b)(λab.a))(λab.b))(λab.ab) = β (λab.ab)(λab.b)(λa.a(λab.b)(λab.a))(λab.b) = β (λb.(λab.b)b)(λa.a(λab.b)(λab.a))(λab.b) = β (λab.b)(λa.a(λab.b)(λab.a))(λab.b) = β (λb.b)(λab.b) = β (λab.b) F 6.3 λ - Ausdruck erstellen (10 Teilpunkte) Schreiben Sie einen λ - Ausdruck, der rekursiv die Quadrate aller natürlichen Zahlen von 0 bis n addiert. Sie können dabei die folgenden Funktionen als gegeben voraussetzen: A(Addition) M(Multiplikation) P(Vorgänger) Y(Fixpunktoperator) Z(Vergleich auf 0) sumquad :: Integer -> Integer sumquad = if n == 0 then 0 else (n*n) + sumquad (n-1) sumquad Y (λrn. (Zn) (0) (A(M(n)(n))(r(P n)))) }{{}}{{}}{{} if else then 10