Funktionale Programmierung (ALP 1), WS 2011/12 — 1. Übungsblatt Test ab 24. Oktober 2011 Bei Funktionen ist generell eine geeignete Typdeklaration anzugeben. 1. Dreiecke (10 Punkte) Schreiben Sie eine Funktion zum Testen, ob x, y, z die Seitenlängen eines Dreiecks (mit positiver Fläche) sind. (Entartete Dreiecke, wo zum Beispiel zwei Ecken zusammenfallen, sind ausgeschlossen.) 2. Negative Argumente (10 Punkte) Die zweistelligen Funktionen mod x y und div x y bestimmen den Rest von x bei Division durch y, beziehungsweise den ganzzahligen Quotienden der Division unter Vernachlässigung des Restes. (a) Finden Sie durch Probieren heraus, was passiert, wenn für x und y auch negative Werte oder 0 eingesetzt werden. (b) Welche Beziehung gilt immer (mit wenigen Ausnahmen; mit welchen?) zwischen x - mod x y und div x y? (c) Fassen Sie Ihre Ergebnisse zu Aufgabe (a) in möglichst einfache Regeln. 3. Überlauf (10 Punkte) Im Gegensatz zum Typ Integer haben Größen vom Typ Int einen Wert von höchstens 231 − 1 = 2.147,483.647 beziehungsweise 263 − 1 = 9,223.372,036.854,775.807. (a) Was passiert, wenn bei einer Rechnung mit Größen vom Type Int diese Grenze überschritten wird? (b) Welches ist der kleinste Wert, der im Typ Int dargestellt werden kann? 4. Zinseszinsberechnung (10 Punkte) Die folgende Funktion bestimmte die Zinsen einer Anlage von zinsfuß %. zinsen kapital zinsfuß = kapital * zinsfuß * 0.01 (a) Definieren Sie unter Zuhilfenahme von zinsen eine Funktion endwert (mit geeigneten Parametern), die den Wert der Anlage (Kapital+Zinsen) am Ende einer Zinsperiode bestimmt. (b) Definieren Sie eine Funktion endwert2, die den Wert nach zwei Zinsperioden berechnet, wenn die Zinsen am Ende der ersten Periode wieder angelegt werden. (c) Funktioniert es auch mit der folgenden Definition? zinsen kapital zinsfuß = kapital * zinsfuß / 100 5. Gleitkommarechnungen (10 Punkte) Vom mathematischen Standpunkt aus müsste die folgende Funktion immer 0 liefern: zero:: Float -> Float zero x = (1/x)*x - 1 Wegen Rundungsfehlern ist dies nicht immer der Fall. Finden Sie Werte x, bei denen das Ergebnis von 0 verschieden ist. (Ändert sich das Ergebnis beim Übergang zu Double?) 6. (10 Punkte) Schreiben Sie eine Funktion von drei Integer-Parametern, die ausgibt, wie viele der Eingabeparameter größer als der Durchschnittswert sind. 1 Funktionale Programmierung (ALP 1), WS 2011/12 — 2. Übungsblatt Korrigierte Fassung von Aufgabe 11b–c (29.10.) — Test ab 31. Oktober 2011 Bei allen Funktionen ist generell eine Typdeklaration anzugeben. 7. Uhrzeiten (10 Punkte) Uhrzeiten wie 10:30 Uhr oder 23:59 Uhr sollen als geordnete Paare (10, 30) beziehungsweise (23,59) dargestellt werden. Schreiben Sie eine Funktion, die die Dauer zwischen zwei Uhrzeiten in Stunden und Minuten berechnet (negativ, falls die zweite Uhrzeit vor der ersten liegt). Sie sollten das Problem in Teilprobleme zerlegen und geeignete Hilfsfunktionen definieren. 8. Uhrzeiten (10 Punkte) Im angelsächsischen Raum werden Uhrzeiten in einem 12-Stunden-Bereich angegeben und mit dem Zusatz a.m. (Vormittag), p.m. (Nachmittag), noon oder midnight versehen: 0:00 = 12:00 midnight, 0:13 = 12:13 a.m., 10:30 = 10:30 a.m., 12:00 = 12:00 noon, 12:55 = 12:55 p.m., 13:20 = 1:20 p.m., 23:59 = 11:59 p.m.. Die Stundenzahl ist also immer zwischen 1 und 12. Schreiben Sie eine Funktion, die dieses Format (als Zeichenkette) berechnet, wenn die Eingabe wie in Aufgabe 7 gegeben ist. Wenn die Eingabe keine gültige Uhrzeit darstellt, soll der Text ungültig ausgegeben werden. 9. Multiplikationstabelle (10 Punkte) | 1 2 10 ---+---------1 | 1 2 10 2 | 2 4 20 10 | 10 20 100 Erstellen Sie eine Tabelle für das kleine Einmaleins (die Produkte aller Zahlenpaare zwischen 1 und 10) als Zeichenkette. Die einzelnen Zeilen sind mit ’\n’ abgeschlossen. Das reduzierte Beispiel rechts zeigt, wie so eine Tabelle aussehen könnte, wenn man sie mit putStr ausgibt. Die Spalten ihrer Tabelle müssen vertikal ausgerichtet sein. (Hinweis: die Funktion show wandelt eine Zahl in eine Zeichenkette um.) 10. Bedingte Ausdrücke (10 Punkte) Schreiben Sie die folgende Funktion als einen einzigen (nicht geschachtelten) if-thenelse-Ausdruck: test x y z | x <= y = True | y <= z = False | otherwise = x < z Zusatzfrage (0 Punkte): Kommt man auch ganz ohne if-then-else-Ausdruck aus? 11. Perfekte Zahlen (10 Punkte) (a) Schreiben Sie eine Funktion, die zu einer Zahl n die Liste ihrer (positiven) Teiler berechnet. (b) Bestimmen Sie jede Zahl n zwischen 1 und 1000, bei der die Summe ihrer von n verschiedenen Teiler größer ist als die Zahl n selbst. (Hinweis: Die Funktion sum berechnet die Summe der Elemente einer Liste) (c) Bestimmen Sie alle perfekten Zahlen zwischen 1 und 1000: die Zahlen n, die gleich der Summe ihrer von n verschiedenen Teiler sind. 2 Funktionale Programmierung (ALP 1), WS 2011/12 3. Übungsblatt Bei allen Funktionen ist generell Test ab 7. November 2011 eine Typdeklaration anzugeben. 12. Sichtbarkeitsbereiche (10+10 Punkte) Geben Sie für jeden eingeführten Namen den Sichtbarkeitsbereich an. (a) (b) x = 25:: Integer biggerThanAVG3:: Integer->Integer->Integer->Integer biggerThanAVG3 x y z = sum (map (\x -> if fromIntegral x > avg3 x y z then 1 else 0) [x ,y, z]) where avg3:: Integer->Integer->Integer->Double avg3 a b c = fromIntegral (a+b+c) / 3 test1:: Integer test1 = biggerThanAVG3 3 4 5 fläche:: Float -> Float fläche x = 2*x^2*pi -- Fläche eines Kreises mit Radius x f x y = let n = 3 in take n (g y) ++ take n (g x) where g x = take n xys where xys = [x] ++ yxs yxs = [y] ++ xys n = 10 13. (10 Punkte) Schreiben Sie eine Funktion, die berechnet, wie viele Zahlen in einer Liste von Integer-Werten kleiner als der Durchschnittswert sind. 14. Preisberechnung (10 Punkte) Listen der beiden folgenden Datentypen type Einkaufsliste = [(String, Float)] type Preisliste = [(String, Float)] geben an, was zum Beispiel gekauft werden soll und vieviel (in einer passenden Einheit, z. B. kg), [("Mehl",0.5), ("Butter",0.25)], und andererseits den Preis in Euro pro Einheit für jeden Artikel. (a) Denieren Sie eine Funktion preis:: Preisliste -> Einkaufsliste -> (Float,[String]) zur Berechnung des Gesamtpreises aller Artikel einer Einkaufsliste. Die zweite Komponente des Ergebnisses soll die Liste der Artikelnamen enthalten, die in der Preisliste nicht gefunden wurden. (b) Erweitern Sie die Funktion so, dass der Preis für jeden gekauften Artikel der Einkaufsliste auf Cent gerundet wird. 3 15. Funktionsiteration (10 Punkte) Die folgende Funktion gument x iter wendet eine Funktion f n-mal hintereinander auf ein Ar- iter 3 f x das Ergebnis f (f (f (x))), das man f 3 (x) oder noch genauer f (3) (x) schreibt, damit man an. Zum Beispiel liefert der Mathematik manchmal als nicht mit der Potenz (f (x))3 in es verwechselt. iter n f x | n==0 = x | n>0 = f (iter (n-1) f x) (a) Welchen Typ hat iter? iter n f ohne den Parameter x. der Funktion iter und der Lösung (b) Geben Sie eine alternative Denition als Funktion (c) Lösen Sie Aufgabe 4b (Zinseszinsen) mit Hilfe von Aufgabe 4a. (Achten Sie auf die Reihenfolge der Argumente.) 16. Iterierter Logarithmus (10 Punkte) logBase a x = loga x y , für die ay = x ist. Die Funktion ist die Zahl berechnet den Logarithmus von (a) Bestimmen Sie die kleinste Zahl (b) Bestimmen Sie die kleinste Zahl x, x, für die für die x zur Basis logBase 2 x >= 5 ist. iter 3 (logBase 2) x >= 2 a; das ist. 17. Potenzieren, Summe und Produkt (10 Punkte) Das Potenzieren mit einer natürlich Zahl als Exponent kann man als iteriertes Multiplizieren denieren: xn := x · x · x · · · x mit n Faktoren: potenz x n = iter n (x*) 1 x xx ·x ·· turm x k = x ↑ k := ist eine geschachtelte Potenz, bei x insgesamt k -mal vorkommt. (Potenzieren ist rechtsassoziativ!) Denieren Sie diese Funktion unter Verwendung von potenz und iter. (a) Die Turmfunktion der in dem Turm auf der rechten Seite (b) Die Multiplikation kann als iterierte Addition aufgefasst werden. Schreiben Sie eine entsprechende Funktion mal a b, die analog zur Funktion potenz das Produkt als iterierte Summe deniert. (c) Welche Funktion muss man iterieren, damit man die a+b Summenfunktion plus a b = erhält? Schreiben Sie eine entsprechende Funktionsdenition für plus. 18. Funktionsiteration (10 Punkte) (a) Jemand hat die Funktion aus der Funktion alle n≥0 g g = iter 23 deniert. Wie können Sie das Argument 23 entdecke, die für herausnden? Schreiben Sie eine Funktion die folgende Beziehung erfüllt: entdecke (iter n) == n, (b) Addition: Schreiben Sie eine Funktion sumiter mit der Eigenschaft sumiter (iter a) (iter b) == iter (a+b), Verwenden Sie nicht einfach entdecke und +, für alle a, b ≥ 0. sondern suchen Sie eine direktere Denition. (c) Multiplikation: Schreiben Sie eine analoge Funktion a und b. 4 proditer für das Produkt von Funktionale Programmierung (ALP 1), WS 2011/12 4. Übungsblatt Test ab 14. November 2011 19. Funktionen höherer Ordnung (5 Punkte) Drücken Sie die Funktion length mit Hilfe von sum und map und geeigneten selbstdenierten Funktionen aus. (Eine Zeile sollte für die Denition reichen.) 20. Listenfunktionen (10 Punkte) Denieren Sie die Funktionen takeWhile :: (a -> Bool) -> [a] -> [a] splitAt :: Int -> [a] -> ([a],[a]) Der Ausdruck takeWhile p x erzeugt das Anfangsstück einer Liste x, solange die Elemente das Prädikat p erfüllen. splitAt n x spaltet die Liste x nach den ersten n Elementen in zwei Teile auf. (Diese Funktionen sind in Haskell schon deniert. Zum Testen müssen Sie daher andere Funktionennamen wählen.) 21. (5 Punkte) Welchen Typ hat der Ausdruck map ( zinsen 2.25) im Zusammenhang von Aufgabe 4? Was bewirkt diese Funktion? 22. Nichtassoziative Faltung von Listen (10 Punkte) Beschreiben Sie das Ergebnis der Funktion differenzen:: Integer -> Integer -> Integer -> Integer differenzen a b c = foldr (-) a [b..c] durch eine explizite Formel in den Gröÿen a, b, c (oder mehrere Formeln). Beweisen Sie Ihre Formel (zum Beispiel durch vollständige Induktion nach c − b, oder auch direkt). 23. Strukturelle Induktion (40 Punkte) (a) (5 Punkte) Beweisen Sie: map f (a ++ b) = map f a ++ map f b (b) (5+10 Punkte) Wie kann man foldr g z (a ++ b) durch foldr auf den Listen a und b ausdrücken? Beweisen Sie Ihre Formel. (c) (5 Punkte) Drücken Sie elem x l durch map und foldr aus, und beweisen Sie damit elem x (a ++ b) = elem x a || elem x b, indem Sie Aufgabe (a) und (b) verwenden. (d) (10 Punkte) Beweisen Sie (take k) . (take l) = take (min k l) Ergänzen Sie bei jeder Behauptung den Gültigkeitsbereich der in der Gleichung vorkommenden Variablen. 24. Lauflängenkodierung (run-length encoding) (a) (10 Punkte) Bei der Lauflängenkodierung wird eine Kette "aaaabbaaa" mit vielen wiederholten Zeichen komprimiert, indem man die Länge jedes Laufes von gleichen Zeichen nimmt: [(4,'a'), (2,'b'), (3,'a')]. Schreiben Sie eine Funktion, die diese Kodierung berechnet, und auch die Umkehrfunktion für die Dekodierung. (b) (10 Punkte) Unter der Annahme, dass die Eingabekette keine Ziern enthält, kann man die komprimierte Fassung kompakter als Kette "4a2b3a" darstellen. Erweitern Sie die vorige Aufgabe auf diese Darstellung 5 Funktionale Programmierung (ALP 1), WS 2011/12 5. Übungsblatt Test ab 21. November 2011 Bei allen Funktionen ist wie immer eine Typdeklaration anzugeben. 25. Sichtbarkeitsbereiche (5 Punkte) Korrigieren Sie die Benennung der Variablen in der Funktion biggerThanAVG3 von Auf- gabe 12a (3. Übungsblatt) so, dass die Funktion berechnet, wie viele der drei Eingabeparameter gröÿer als der Durchschnittswert sind (Aufgabe 6 vom 1. Übungsblatt). 26. Anonyme Funktionen (λ-Ausdrücke) (15 Punkte) Wandeln Sie folgende Funktionsdenitionen in anonyme Funktionen um, ohne lokale Denitionen mit where oder let zu verwenden. Ihre Lösung soll mit f = \. . . (a) Die Funktion f = biggerThanAVG3 (b) Die Funktion f beginnen. von Aufgabe 12a (3. Übungsblatt) von Aufgabe 12b (3. Übungsblatt) (c) Ihre Lösung von Aufgabe 25. (d) f x y z = x^3 - g (x + g (y - g z) + g (z^2)) where g x = 2*x^2 + 10*x + 1 Ein Trick: Sie können sich das explizite Hineinkopieren der Funktion g an mehrere Stellen sparen, indem Sie zunächst g als zusätzlichen (ersten) Parameter Ihrer Funktion denieren. 27. Zinseszinsen (10 Punkte) Die Funktionen Funktion foldr scanr und scanl liefern foldl: eine Liste mit allen Zwischenergebnissen der beziehungsweise scanr:: (a scanl:: (b scanr op z scanr op z -> b -> b) -> b -> [a] -> [b] -> a -> b) -> b -> [a] -> [b] [] = [z] (x:xs) = (x op q) : q:qs where (q:qs) = scanr op z xs scanl op a [] = [a] scanl op a (x:xs) = a : scanl op (a op x) xs k0 über mehrere Jahre entwi[z1 , z2 , . . . , zn ] der jährlichen Verzinsungen gegeben ist. Verwenden Funktion scanr oder scanl, sowie geeignete Funktionen von Aufgabe 4. Eine Funktion soll berechnen, wie sich ein Anfangskapital ckelt, wenn die Folge Sie dazu die 28. Abarbeiten von Listen (15 Punkte) (a) Welche Beziehung besteht zwischen dem Ergebnis von und scanr (+) 333 [1..10]? scanl (-) 333 [1..10] (b) Welche Beziehung besteht allgemein zwischen dem Ergebnis von und scanr (+) a x? scanl (-) a x Welche Beziehung besteht zwischen aufeinanderfolgenden Elementen in jeder dieser Listen? Beweisen Sie Ihre Aussagen. f und g gelten, damit eine analoge Beziehung zwischen scanl f a x und scanr g a x besteht? (Untersuchen Sie genau, welche Eigenschaften von + und - Sie in Ihrem Beweis zu Aufgabe (b) benötigt (c) Welches Gesetz muss für die Operationen haben.) 6 29. Sortieren durch Auswählen (10 Punkte) Bei diesem Sortierverfahren wird das kleinste Element einer Liste ausgewählt und an den Anfang gestellt; die restlichen Elemente werden rekursiv sortiert. Programmieren Sie dieses Sortierverfahren in Haskell. 30. Verbinden von Listen, Faltung (5 Punkte) (a) Denieren Sie die Funktion ++ durch eine geeignete Faltung. (b) Bei der Lösung von Aufgabe 9 war eine Funktion hilfreich, die eine Liste von Zeichenketten zu einer einzigen Zeichenkette zusammenfügt (In der Musterlösung heiÿt diese Funktion aneinander:: [String] -> String, in Haskell gibt es daconcat:: [[a]] -> [a].) Denieren Sie diese Funktion für die Standardfunktion durch Faltung. 31. Verbinden und Trennen von Listen (20 Punkte) (a) Denieren Sie eine Funktion, die eine Liste von Listen mit einem Verbindungsglied zusammenfügt. Das Verbindungsglied soll zwischen den Elementen erscheinen, aber nicht am Ende nach dem letzten Element. Hier sind Beispiele: verbinden verbinden verbinden verbinden :: ", ", ", [a] -> [[a]] -> [a] " [] = "" " ["eins"] = "eins" " ["erstens","2.","drittens"] = "erstens, 2., drittens" trennen :: [a] -> [a] -> [[a]] soll die Liste an den Stellen trennen, wo das Verbindungsglied vorkommt, sodass für alle x die Gleichung verbinden x . trennen x = id gilt. Überlegen Sie, ob die Lösung immer ein- (b) Die Umkehrfunktion deutig ist. Beschreiben Sie klar und eindeutig (d.h., spezizieren Sie), was Ihre Umkehrfunktion in jedem Fall machen soll. (c) Denieren Sie die Umkehrfunktion nach Ihrer Spezikation. (d) Warum ist es unmöglich, durch eine Funktion trennen x . verbinden x = id trennen für alle x die Gleichung x, für die man zu erfüllen? Gibt es Werte von die Beziehung erfüllen kann? 32. Funktionen höherer Ordnung (10 Punkte) Welche der folgenden Funktionen ersetzt jedes Vorkommen eines bestimmten Wortes in einer Liste von Wörtern durch eine Folge von Sternen? Bestimmen Sie für jede Funktion, ob Sie überhaupt nach den Haskell-Regeln gültig ist, und stellen Sie gegebenenfalls ihren Typ fest. wiederhole n x = [ ersetzeWort unwort | unwort == w = | otherwise = zensiere1 unwort = zensiere2 unwort = zensiere3 unwort = zensiere4 unwort = zensiere5 = zensiere6 unwort = zensiere7 unwort = zensiere8 = x | k <- [1 .. n]] -- = die Standardfunktion replicate w wiederhole (length unwort) '*' w map (ersetzeWort unwort) map ersetzeWort unwort map unwort . ersetzeWort map . ersetzeWort unwort map . ersetzeWort (map . ersetzeWort) unwort ersetzeWort unwort . map map ersetzeWort 7 Funktionale Programmierung (ALP 1), WS 2011/12 Probeklausur vom 21. November 2011 1. Fläche eines Polygons (10 Punkte) Die Fläche eines n-Ecks mit den Ecken (x1 , y1 ), . . . , (xn , yn ) ist durch die Formel n X (x − x )(y + y ) i+1 i i+1 i F = 2 i=1 gegeben, wobei xn+1 für x1 und yn+1 für y1 steht. Schreiben Sie eine Funktion für diese Formel. (Die Funktion für den Absolutbetrag heiÿt abs.) Bei allen Funktionen ist wie immer eine Typdeklaration anzugeben. 2. Sichtbarkeitsbereich (10 Punkte) (a) (7 Punkte) Geben Sie für jeden im folgenden Programmstück eingeführten Namen den Sichtbarkeitsbereich an. f x y | r > 0 | otherwise where r = g g z x = = x = x+r -x+y (-y) x*y*z - 1 (b) (3 Punkte) Bestimmen Sie [f (-1) (-1), f (-1) 2, f (-2) 1]. 3. (a) (10 Punkte) Welche der folgenden Denitionen bewirkt, dass die Funktion g = entf? ' ' alle Leerzeichen aus einer Zeichenkette entfernt? entf1 entf2 entf3 entf4 entf4 entf4 entf5 z z z z z z z = concat . map (\ x -> if x==z then "" else x) l = [if x==z then "" else [x] | x <- l] = foldr (\ x r -> if x==z then r else x:r) [ ] [] = [] (z:zs) = entf4 z zs (x:xs) = x: entf4 z xs l = [x | x <- l, x/=z] Bestimmen Sie für jede Funktion entfn, ob sie überhaupt nach den Haskell-Regeln gültig ist, und stellen Sie gegebenenfalls ihren Typ fest. Begründen Sie Ihre Antworten. (b) (5 Punkte) Was macht die Funktion entf '.' . entf ',' . entf '.' . entf ';' . entf '.', wobei entf die richtige Lösung zu Aufgabe (a) ist? 4. Strukturelle Induktion (15 Punkte) Wie kann man foldl g a (u ++ v) durch foldl auf den Listen u und v ausdrücken? Beweisen Sie Ihre Formel unter Verwendung der folgenden Denitionen. (F0 ) (F1 ) (++0 ) (++1 ) foldl:: (b -> a -> b) -> b -> [a] -> b foldl g a [] = a foldl g a (x:xs) = foldl g (g a x) xs (++):: [a] -> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys) 8 Funktionale Programmierung (ALP 1), WS 2011/12 6. Übungsblatt Test ab 28. November 2011 und ab 5. Dezember 2011 Bei allen Funktionen ist wie immer eine Typdeklaration anzugeben. 33. (8 Punkte) Die Funktion filter p l wählt aus einer Liste l alle Elemente aus, die das p erfüllen. Denieren Sie eine solche Funktion Prädikat (die Boolesche Funktion) filter:: (a->Bool) -> [a] -> [a] (a) rekursiv, (b) durch Listendurchlauf (Zermelo-Fränkel-Notation). (c) Schreiben Sie mit Hilfe von filter eine Funktion, die alle Leerzeichen aus einer Zeichenkette entfernt. 34. Auswertungsstrategien (10 Punkte) Die Funktion foldr:: foldl:: foldr f foldr f foldl f foldl f foldr und (a -> b -> (b -> a -> z [] = z (x:xs) = a [] = a (x:xs) = foldl sind folgendermaÿen deniert: b) -> b -> b) -> b -> z f x (foldr a foldl f (f [a] -> b [a] -> b f z xs) a x) xs Vollziehen Sie nach, wie die Ausdrücke mit der Funktion g x y = x+2*y foldr g 0 [1,2,3] und foldl g 0 [1,2,3] Schritt für Schritt ausgewertet werden, und zwar bei (a) strenger Auswertung von innen nach auÿen, und (b) träger Auswertung (Bedarfsauswertung) wie in Haskell. 35. (10 Punkte) Lösen Sie die vorige Aufgabe mit der Funktion foldl': foldl':: (b -> a -> b) -> b -> [a] -> b foldl' f a [] = a foldl' f a x = f (foldl' f a (init x)) (last x) last :: [a] -> a last [x] = x last (_:xs) = last xs init :: [a] -> [a] init [_] = [] init (x:xs) = x : init xs 36. Darstellung von Ausdrücken (10 Punkte) (a) Schreiben Sie eine Funktion, die für eine Darstellung vom Typ Ausdruck (Vorle- sung vom 16. 11. 2011), die keine Variablen enthält, den durch den arithmetischen Ausdruck gegebenen Wert berechnet. (b) Schreiben Sie eine Funktion, die als zusätzliche Eingabe eine Werteliste vom Typ [(String,Integer)] akzeptiert, wobei ein Element ten soll, dass die Variable mit Namen "x" ("x",3) zum Beispiel bedeu- den Wert 3 hat. Falls der Ausdruck eine Variable enthält, die nicht in der Liste vorkommt, soll die Funktion mit einer informativen Fehlermeldung abbrechen. 9 37. Strenge Funktionen (7 Punkte) Eine Funktion f in Haskell ist ausgewertet wird, wenn f streng x, in einem Parameter wenn x auf jeden Fall ausgewertet wird. In welchen Parametern sind die folgenden Funktionen streng? doppel n a = a+a f1 n a = if n=0 then a+1 else a-n f2 n a = if n=0 then a+1 else n 38. Träge Multiplikation (5 Punkte) Schreiben Sie eine Funktion mult zur Multiplikation zweier Zahlen, die das zweite Ar- gument nicht auswertet, wenn das erste Argument 0 ist. 39. Spiegeln von zweidimensionalen Mustern (10 Punkte) Man kann rudimentäre Graken als Zeichenketten erzeugen, die aus durch \ +--> \ | +---+ '\n' abgeschlossenen Zeilen bestehen und mit putStr ausgegeben putStr "\\ +-->\n \\ |\n +---+\n" das obige werden. Zum Beispiel liefert Bild. (Verkehrte Schrägstriche müssen in einer Zeichenkette doppelt eingegeben werden, \n unterscheiden kann.) flipV, die eine solches Bild an damit man sie von Sonderkodierungen wie Schreiben Sie Funktionen flipH und einer horizontalen beziehungsweise an einer vertikalen Achse spiegeln. Das Ergebnis soll bei diesem Beispiel so aussehen: flipH: >--+ \ | \ +---+ flipV: +---+ \ | \ +--> 40. Die Fibonacci-Zahlen (10 Punkte) (a) Die Folge F1 , F2 , . . . der Fibonacci-Zahlen ist durch die Anfangswerte F1 = F2 = 1 und die Rekursion Fn = Fn−1 + Fn−2 für (∗) n ≥ 3 gegeben. Schreiben Sie ein Programm zur Berechnung der n-ten Fibonacci- Zahl. Berechnen Sie die ersten 20 Fibonacci-Zahlen. (b) Welche Werte ergeben sich für Fn mit n ≤ 0, wenn man die Gültigkeit der Gleichung (∗) auf alle ganzen Zahlen n ausdehnt? Erweitern Sie Ihr Programm, sodass es auch eine negative Eingabe akzeptiert. 27 41. Kodierung von Bäumen (10 Punkte) Nach einer alternativen Denition von Bäumen ist ein Blatt (ein einzelner Knoten ohne Kinder) oder ein innerer Knoten mit genau 5 nichtleerer Baum entweder ein zwei Kindern. data Baum' a = Blatt a | Knoten a (Baum' a) (Baum' a) −2 44 7 8 5 7 9 Man kann einen solchen Baum kodieren, indem man augehend von der Wurzel einmal auÿen um den Baum herumgeht und dabei jede Abwärtsbewegung (Down), jede Aufwärtsbewegung (Up) und jeden Knoten notiert, wenn er zum erstenmal besucht wird. Das nebenstehende Beispiel liefert etwa den Kode 27D5D-2UD7UUD44D8UD5D7UD9UUU. Schreiben Sie ein Programm, das diesen Kode für einen Baum vom Typ berechnet. 10 Baum' Int Funktionale Programmierung (ALP 1), WS 2011/12 7. Übungsblatt Test ab 12. Dezember 2011 42. Zeichnen von Weihnachtsbäumen (10 Punkte) Schreiben Sie ein Programm, das eine Baum mit ganzzahligen Knotenwerten mit Buchstabengrak ausgibt, zum Beispiel wie im nebenstehenden Bild. (Sie dürfen eine Annahme über den Wertebereich machen, wenn Sie sie dokumentieren.) 43. Der Teilabschnitt mit der gröÿten Summe (10 Punkte) Schreiben Sie eine Funktion, die für einer Liste gröÿte Summe ai + ai+1 + · · · + aj zusammenhängenden [a1 , . . . , an ] die einer in ihr enthaltenen Teilfolge bestimmt. (Die Summe der leeren Folge ist 0.) 44. Typklassen und Typinferenz (5 Punkte) 12 | +---+---+ | | 777 16 | | +-+-+ +-+-+ | | | | 12 22 426 -12 | | | +-+ +++ +-+ | | | | 16 13 6 1 concat . map show, map length . sum. Verwenden Sie den Bestimmen Sie den Typ der Funktionen sum . map length, und Computer höchstens zum Überprüfen Ihrer Antworten. 45. Typinferenz (15 Punkte) Bestimmen Sie die Typen der Funktionen = f x y, und id x = x. curry f x y = f (x,y), uncurry f (x,y) Stellen Sie fest, welche der folgenden acht Funktionen gültig sind, und bestimmen Sie gegebenfalls ihren Typ: curry id uncurry id curry (curry id) uncurry (uncurry id) uncurry curry curry uncurry uncurry uncurry curry curry 46. Wahrheitstafel für Boolesche Funktion (15 Punkte) Schreiben Sie eine Funktion zum Erstellen einer Wahrheitstafel für Boo- Bool -> Bool -> · · · -> Bool. Beim Anwenden auf k eine k -stellige Funktion soll für jede der 2 Belegungen der Parameter mit True oder False der Funktionswert tabelliert werden. Zum Beispiel könnte für die Funktion (\x y z -> x && y || z) das nebenstehende Ergebnis herauskommen. Die Stellenzahl k soll nicht als Parameter der lesche Funktionen Funktion verlangt werden. T T T T F F F F T T F F T T F F T F T F T F T F | | | | | | | | T T T F T F T F 47. Uhrzeiten (15 Punkte) (a) (5 Punkte) Schreiben Sie eine eigene show-Funktion für den Datentyp Uhrzeit aus Show. der Vorlesung vom 16. 11. und deklarieren Sie ihn als Beispiel der Typklasse Sie können dabei das angelsächsische Format wie in Aufgabe 8 nehmen oder das bei uns gebräuchliche 24-Stunden-Format. Uhrzeit als Beispiel der Typklasse Enum. Sie müssen fromEnum und toEnum denieren. Drücken Sie dann mit Hilfe der folgenden Funktion, die in der Typklasse Enum bereits vordeniert ist, die Liste (b) (10 Punkte) Deklarieren Sie dazu die Funktionen der Uhrzeiten alle 15 Minuten von 10:28 bis 16:13 Uhr aus. enumFromThenTo x y z = map toEnum [ fromEnum x, fromEnum y .. fromEnum z ] 11 Funktionale Programmierung (ALP 1), WS 2011/12 8. Übungsblatt Test ab 24. Dezember 2011 48. Ein- und Ausgabe (10 Punkte) Schreiben Sie ein Programm für folgende Aufgabe: Der Benutzer wird nach dem Namen eine Eingabedatei und einer Ausgabedatei gefragt; dann wird die Eingabedatei auf die Ausgabedatei kopiert, wobei Folgen von Leerzeichen am Zeilenende weggelassen werden. 49. Bäume dekodieren (10 Punkte) Schreiben Sie ein Programm für die Umkehrfunktion zu Aufgabe 41. 50. Intervallhalbierung, binäre Suche (10 Punkte) nullStelle:: (Floating a, Ord a) => (a -> a) -> a -> a -> a -> a zum Finden einer Näherungslösung x der Gleichung f (x) = 0 für eine stetige reelle Funktion f : [a, b] → R, die auf einem Intervall [a, b] deniert ist. Die Funktion nullStelle f a b epsilon setzt voraus, dass f (a) und f (b) verschiedenes Vorzeichen haben. Wegen der Stetigkeit von f folgt daraus, dass f im Intervall [a, b] Schreiben Sie ein Programm mindestens eine Nullstelle hat. Das Verfahren der Intervallhalbierung bestimmt zunächst das Vorzeichen von f ((a + b)/2) und grenzt dadurch das Intervall auf die linke oder die rechte Hälfte ein. Dieser Vorgang wird iteriert, bis die Länge des Lösungsintervalls unter ε reduziert ist. Finden Sie mit Ihrem Programm die Lösung von xx = 2, und von ex = sin x, x > −4, x jeweils auf 6 Nachkommastellen genau. Die Exponentialfunktion e wird in Haskell als exp x geschrieben. 51. Die Fibonacci-Folge (13 Punkte) Man kann die Fibonacci-Folge auch bei fibo:: fibo 0 fibo 1 fibo n F0 = 0 beginnen lassen: Integer -> Integer = 0 = 1 | n>1 = fibo (n-1) + fibo (n-2) Wie oft wird beim Aufruf von fibo n die letzte Zeile der Denition ausgeführt? Wie oft wird die erste Zeile ausgeführt? Wie oft die zweite Zeile? Beweisen Sie Ihre Aussagen durch Induktion nach n. 52. Suchen und Einfügen in einem Suchbaum (10 Punkte) data Ord a => Suchbaum a b = Leer | Knoten a b (Suchbaum a b) (Suchbaum a b) (a) Schreiben Sie eine Funktion finde:: Ord a => a -> Suchbaum a b -> Maybe b zum Suchen eines Elements in einem Suchbaum (Vorlesung vom 28. 11.) einf:: Ord a => a -> b -> Suchbaum a b -> Suchbaum a b zum Einfügen eines Elements in einen Suchbaum. Das Ergebnis von einf s t b ist ein neuer Suchbaum, in dem ein zusätzliches Element mit Schlüssel s vom Typ a und Wert t vom Typ b enthalten ist. Sie dürfen annehmen, dass der Schlüssel s vorher nicht im Baum vorkommt. (b) Programmieren Sie eine Funktion 12 53. Bedingte Ausdrücke in primitiv-rekursiven Funktionen (10 Punkte) Beweisen Sie: Wenn f, g, h : Nk → N dann ist auch die folgende Funktion k -stellige drei a primitiv-rekursive Funktionen sind, eine primitiv-rekursive Funktion: a(x1 , . . . , xk ) := if f (x1 , . . . , xk ) = 0 then g(x1 , . . . , xk ) else h(x1 , . . . , xk ) f1 (x1 , . . . , xk ) < f1 (x1 , . . . , xk ) = f2 (x1 , . . . , xk ), falls Beweisen Sie dieselbe Schlussfolgerung auch für Bedingungen der Form f2 (x1 , . . . , xk ), f1 (x1 , . . . , xk ) ≤ f2 (x1 , . . . , xk ) f1 und f2 primitiv-rekursiv sind. und 54. Gröÿe enthaltene Zweierpotenz (10 Punkte) Zeigen Sie, dass die Funktion p2 : N → N p2 (n) := max{ i ≥ 0 | 2i mit ist ein Teiler von n} für n > 0, p2 (0) := 0 primitiv-rekursiv ist. Tipp: Konstruieren Sie zuerst eine Hilfsfunktion h(m, n) := max{ i ≥ 0 | 2i ≤ m + 1 und 2i ist ein Teiler von n} Sie dürfen unter anderem voraussetzen, dass die modulo-Funktion und die Potenzfunktion primitiv-rekursiv ist. 55. Einsetzung (12 Punkte) Klassischerweise wird die Einsetzungsregel bei der Denition der primitiv-rekursiven Funktionen strenger formuliert: Wenn eine k -stellige primitiv-rekursive Funktion primitiv-rekursive Funktionen die n-stellige g1 , . . . , gk : Nk Funktion f : Nk → N und k n-stellige → N gegeben sind, dann ist auch h(x1 , . . . , xn ) := f g1 (x1 , . . . , xn ), g2 (x1 , . . . , xn ), . . . gk (x1 , . . . , xn ) primitiv-rekursiv. Zusätzlich wird dabei deniert, dass alle Projektionsfunktionen Pik (x1 , . . . , xk ) := xi für 1≤i≤k primitiv-rekursiv sind. Zeigen Sie mit dieser Einsetzungsregel und mit Hilfe geeigneter Projektionsfunktionen, dass die Funktionen p(x, y, z) := h(x, h(y, z)) q(x, y, z) := g(h(x, y), y, g(z, z, y)) primitiv-rekursiv sind, falls die Funktionen g und h als primitiv-rekursiv vorausgesetzt werden. 56. Suchbäume (10 Punkte) Schreiben Sie eine Funktion, die überprüft, ob ein Suchbaum richtig sortiert ist. (Das heiÿt, ob die Suchbaumeigenschaft erfüllt ist: Für jeden Knoten mit Schlüssel s müssen die Knoten im linken Teilbaum kleinere Schlüssel als s haben und die Knoten im rechten Teilbaum gröÿere Schlüssel.) 57. Verschmelzen (5 Punkte) Scheiben Sie eine Funktion verschmelze:: (Ord a) => [a] -> [a] -> [a], die zwei aufsteigend sortierte Listen zu einer sortierten Gesamtliste vereinigt. Zum Beispiel: verschmelze [1,3,4,7] [2,3,7,8,10] = [1,2,3,3,4,7,7,8,10] 13 Weihnachtsaufgaben Julian Fleischer 5. März 2012 Dies sind freiwillige Zusatzaufgaben, mit denen Sie im Rahmen einer etwas größeren Programmieraufgaben den Umgang mit einem svn-Repository üben können. Für die Bearbeitung der Aufgaben ist ein SVN-Repository unter http://dev.spline.de anzulegen. Hierfür ist lediglich eine E-Mail-Adresse @...fu-berlin.de nötig, also z.B. die FU-Adresse, die man über das Zedat-Portal benutzen kann (zumeist [email protected] oder [email protected]). Als Abgabe schicken Sie dann bitte einfach Name, Matrikelnummer, und den Link zu Ihrem Repository (also z.B. https://dev.spline.de/svn/huffman_alp1/ bis zum 1.1.2012 an Ihren Tutor/Ihre Tutorin. Falls Ihr Repository nicht öffentlich ist, vergessen Sie nicht, Ihren Tutor oder Ihre Tutoring in das Projekt einzuladen. Die Abgabe kann in Projektgruppen zu 2 oder 3 Leuten erfolgen. Hilfe erhalten Sie im Forum.1 Aufgabe W1, 20 Punkte: RSA-Verschlüsselung Das RSA-Verfahren2 ist ein wichtiges Verfahren der Nachrichtenverschlüsselung mit öffentlichen Schlüsseln, zum Beispiel bei Datenübertragung im Internet. Entwickeln Sie eine Programm, das eine einfache RSA-Verschlüsselung erlaubt. Im öffentlichen Repository https://dev.spline. de/svn/rsa_alp1_aufgabe2/ gibt es ein Grundgerüst für Ihre Anwendung. a) Vervollständigen Sie die Funktion rsaEncode (5 Punkte). b) Vervollständigen Sie die Funktion rsaDecode (5 Punkte). c) Enschlüsseln Sie dien verschlüsselte Nachricht[7321434, 3598567, 1716197, 4119550, 1716197, 1348875, 8435094, 8273804, 543720, 4505902, 4941202, 6726051, 8083299, 4896702, 3790340, 8176577, 3956251, 3855025, 9779898, 9626936, 7581573, 530038, 5596561, 1789054, 3956251, 3855025, 9779898, 1631514, 8435094, 9779898, 60307, 7379435]. d) Schreiben Sie eine interaktive Ein/Ausgabe-Routine main, die es erlaubt, Ihr Programm zu bedienen. Aufgabe W2, 20 Punkte: Symbolischer Gleischungslöser Entwickeln Sie ein Programm, das Gleichungen lösen kann. Checken Sie hierfür das öffentliche Repository https://dev.spline.de/svn/symbolic_equation_solver_alp1 aus, in dem es ein Grundgerüst für Ihre Anwendung gibt. a) Erweitern Sie die Datenstruktur Term, so dass auch Produkte und Brüche dargestellt werden können. b) Implementieren Sie die fehlenden Funktionen der Instanz von Term für die Klasse Num. Beachten Sie, dass sie Terme zwischendurch vereinfachen oder ordnen müssen (a + b ist der gleiche Term wie b + a, und a + a ist der gleiche Term wie 2 ∗ a) — wahrscheinlich werden sie eine kanonische Darstellung definieren müssen. c) Vervollständigen Sie die Ein/Ausgabe-Routine main zur Bedienung Ihres Programms. 1 2 https://foren.spline.inf.fu-berlin.de/viewforum.php?f=474 http://de.wikipedia.org/wiki/RSA-Kryptosystem 14 Funktionale Programmierung (ALP 1), WS 2011/12 9. Übungsblatt Test ab 10. Januar 2012 58. Die Ackermannfunktion (10 Punkte) Eine Variante der Ackermannfunktion beginnt mit der Nachfolgerfunktion: B0 (n) = n + 1, für n ≥ 0 Bi (0) = 2, für i ≥ 1 Bi (n) = Bi−1 (Bi (n − 1)), für i ≥ 1, n ≥ 1 (Die Funktion Ai (n) aus der Vorlesung beginnt mit der Verdoppelungsfunktion A0 (n) = 2n und hat Anfangswerte Ai (0) = 1 für i ≥ 1. Die allgemeine Rekursion ist wie bei B .) (a) Finden Sie durch Probieren Formeln für B1 (n), B2 (n), B3 (n). (b) (Zusatzaufgabe, 0 Punkte). Beweisen Sie die Formeln durch vollständige Induktion. (c) Zeigen Sie, dass B2 (n) ≥ A0 (n) ist, dass B3 (n) ≥ A1 (n) ist, und dass generell Bi+2 (n) ≥ Ai (n) ist. (Das Wachstum von B hinkt dem Wachstum von A also höchstens zwei Schritte hinterher.) 59. (1 Punkt) Was passiert, wenn man in der obigen Aufgabe Bi (0) = 1 für i ≥ 1 schreibt? 60. (10 Punkte) Wörterbuchoperationen Wir möchten die Operationen für ein Wörterbuch um die Operation anzahl:: WBUCH a b -> Int erweitern, die die Anzahl der gespeicherten Schlüssel ausgibt. Wie gut sind die in der Vorlesung angegebenen Implementierungen eines Wörterbuchs dafür geeignet? Wählen Sie eine Implementierung aus und erweitern Sie sie entsprechend. 61. (10 Punkte) Datenstruktur für ein Wörterbuch Modizieren Sie die in der Vorlesung angegebene Implementierung eines Wörterbuchs als algebraischer Datentyp (Modul SpeicherAlg), sodass beim Löschen wirklich gelöscht wird und man mit folgender Typdeklaration auskommt: data WBUCH a b = Leer | Einf a b (WBUCH a b) 62. (10 Punkte) Vereinigung von Wörterbüchern. Ergänzen Sie die algebraische Spezikation von Wörterbüchern um eine Operation vereinige:: WBUCH a b -> WBUCH a b -> WBUCH a b, die den Inhalt zweier Wörterbücher vereinigt. Können Sie ihre Spezikation so gestalten, dass das Ergebnis nicht von der Reihenfolge der Argument abhängt, dass also vereinige w1 w2 äquivalent zu vereinige w2 w1 ist? 63. Bäume (5 Punkte) Schreiben Sie eine Funktion, die die Höhe eines Suchbaums bestimmt. (Vorlesung vom 28. 11.: data (Ord a) => Suchbaum a b = Leer | Knoten a b (Suchbaum a b) (Suchbaum a b) mit Schlüsseln vom Typ a.) Dabei hat ein leerer Suchbaum die Höhe −1 und ein Baum mit einem einzigen Knoten die Höhe 0. 64. Bäume (10 Punkte) Schreiben Sie eine Funktion, die einen Suchbaum in einen Baum vom Type Baum Int umwandelt, wo in jedem Knoten seine Tiefe gespeichert ist. Sie müssen die Typkonstruktoren aus der Vorlesung vom 16. 11. umbenennen, um Sie von Suchbäumen zu unterscheiden: data Baum a = BLeer | BKnoten a (Baum a) (Baum a) 15 Funktionale Programmierung (ALP 1), WS 2011/12 10. Übungsblatt Test ab 17. Januar 2012 65. Orientierungstest (10 Punkte) Bei der Flächenformel eines Polygons, Pn i=1 (xi+1 − xi )(yi+1 + yi )/2, (Aufgabe 1 der Probeklausur) hat das Vorzeichen eine Bedeutung: es ist positiv, wenn der Rand des Polygons im Gegenuhrzeigersinn (im mathematisch positiven Sinn) durchlaufen wird und negativ, wenn er im Uhrzeigersinn (im mathematisch negativen Sinn) durchlaufen wird. Betrachten Sie die Formel im Fall eines Dreiecks (n Funktion orient, = 3) und schreiben Sie eine die berechnet, ob ein Dreieck positiv oder negativ orientiert ist. Ver- einfachen Sie dazu die Formel unter Ausnützung der Tatsache, dass sich die Fläche nicht ändert, wenn man das Dreieck verschiebt, und man daher eine Ecke auf den Nullpounkt legen kann. Wann ergibt die Formel den Wert 0? 66. Backus-Naur-Form (10 Punkte) Dies ist eine rudimentäre Syntax für arithmetische Ausdrücke mit Addition und Multiplikation, aber ohne Klammern: hZieri ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 hZahli ::= hZieri{hZieri} hAusdrucki ::= hZahli | hAusdrucki*hAusdrucki | hAusdrucki+hAusdrucki Zeigen Sie, wie man in dieser Grammatik die Zeichenkette hAusdrucki 30+4*5 aus der Variablen Schritt für Schritt erzeugen kann. Ist dies auf eindeutige Art möglich? 67. Freie und gebundene Variablen (10 Punkte) Bestimmen Sie die freien und gebundenen Variablen in den folgenden Ausdrücken. Benennen Sie die gebundenen Variablen so um, dass in jedem Ausdruck alle λ-Abstraktionen verschiende Variablen binden. λa.(aλb.bca) λf.bλb.(λf.f b) (c) λf g.(λb.h)(λa.b)f g (d) λxy.(λx.y)(λy.x) (e) λpq.(λr.(p(λq.(λp.rq)))(qp)) (a) (b) 68. Auswertung (10 Punkte) Werten Sie die folgenden Ausdrücke Schritt für Schritt aus; und geben Sie auch alle Zwischenergebnisse an. (λxy.yx)(λp.λq.p)(λk.k) (b) (λx.λyz.(xy)z)(λf a.f a)(λk.k)(λj.j) (c) (λf a.f a)(λf a.f a)(λx.x) (d) (λpq.pq)((λx.x)(λab.a))(λk.k) (e) (λf.f f )((λf.f f )(λf a.a))g (a) 69. Nachfolger, Addition und Multiplikation (10 Punkte) Werten Sie die folgenden Ausdrücke aus. (λwnz.n(wnz))(λnz.n(nz)) (b) (λnz.n(n(nz)))(λwnz.n(wnz))(λnz.n(nz)) (c) (λuab.u(ab))(λnz.n(n(n(z))))(λnz.n(n(z))) (d) (λxy.xyλab.b)(λab.a)(λab.b) (e) (λxy.xyλab.b)(λab.b)(λab.a) (a) 16 Funktionale Programmierung (ALP 1), WS 2011/12 11. Übungsblatt Test ab 23. Januar 2012 70. Zwei verschiedene Funktionen für die Addition (10 Punkte) • Im Ausdruck 3Sx wird die Nachfolgerfunktion S = λanz.n(anz) dreimal auf das Argument x angewendet, und das Ergebnis ist S(S(S(x))). 3S2 ist also 5, und generell können wir auf diese Art zwei Church-Zahlen im Lambdakalkül addieren: λab.aSb = λab.a(λanz.n(anz))b • In der Vorlesung wurde die folgende Additionsfunktion eingeführt λab.λnz.an(bnz) = λabnz.an(bnz) Stellen die beiden in (a) und (b) gegebenen Ausdrücke die gleiche Funktion dar, in dem Sinn, dass sie für alle Argumente dasselbe Ergebnis liefern? 71. Negative Zahlen als Paare von natürlichen Zahlen (10 Punkte) Jede Darstellung von natürlichen Zahlen kann zu einer Darstellung aller ganzen Zahlen als Paare natürlicher Zahlen erweitert werden: Das Paar (a, b) ∈ N × N stellt dann die ganze Zahl a − b ∈ Z dar. Auf diese Art kann man negative Zahlen auch im LambdaKalkül einführen. Schreiben Sie eine Haskell-Funktionen, die zu zwei Paaren natürlicher Zahlen (a, b) und (a0 , b0 ) (a) bestimmt, ob sie dieselbe ganze Zahl darstellen; (b) eine Darstellung für die Summe berechnet; (c) eine Darstellung für das Produkt berechnet. 72. Normalisierung (10 Punkte) Die Zahldarstellung der vorigen Aufgabe ist nicht eindeutig. Jede ganze Zahl hat aber eine eindeutige normalisierte Darstellung (a, b) ∈ N × N, wo die Bedingung ab = 0 gilt. Schreiben Sie eine Funktion zum Berechnen einer normalisierten Darstellung für eine gegebene Darstellung einer ganzen Zahl, und zwar sowohl in Haskell als auch im Lambdakalkül. 73. (0 Punkte, freiwillig) Denieren Sie die Potenzfunktion im Lambda-Kalkül. 74. Rekursion (10 Punkte) Denieren Sie die Fakultätsfunktion n 7→ n! im Lambda-Kalkül. 75. Durchlaufen von Bäumen (0 Punkte, freiwillig) Schreiben Sie eine Funktion, die für eine Darstellung eines arithmetischen Ausdrucks vom Typ Ausdruck (Vorlesung vom 16. 11. 2011) die Anzahl der verschiedenen Variablen berechnet. 76. Teilwortsuche (10 Punkte) Schreiben Sie ein Programm, das feststellt ob eine Zeichenkette (z. B. "ab c") in einem längeren Text (z. B. "xyz rstab cde uvw") als Teilkette enthalten ist. Analysieren Sie die Laufzeit Ihres Programmes in Abhängigkeit von der Länge n1 und n2 der beiden Eingaben. Gesucht ist eine obere Schranke in O-Notation. 77. (5 Punkte) Analysieren Sie die Laufzeit Ihrer (oder einer anderen) Lösung zu Aufgabe 43 vom 7. Übungsblatt. (Teilabschnitt mit der gröÿten Summe). Gesucht ist eine Schranke der Form O(f (n)) für eine geeignete Funktion f . 17 Funktionale Programmierung (ALP 1), WS 2011/12 12. Übungsblatt Test ab 30. Januar 2012 78. Zwei verschiedene Funktionen für das logische Und (5 Punkte) In der Vorlesung wurden zwei verschiedene Möglichkeiten λxy.xyx und λxy.xyF = λxy.xyλuv.v für die Konjunktion im Lambda-Kalkül vorgestellt. Stellen diese beiden Ausdrücke die gleiche Funktion dar, in dem Sinn, dass sie für alle Argumente dasselbe Ergebnis liefern? 79. Die Ausgabemonade (10 Punkte) Rechnen Sie nach, dass die Ausgabe-Monade (Vorlesung vom 23. Januar) die Monadengesetze erfüllt: p >>= return = p, return x >>= f = f x, und (p >>= \x -> q) >>= r = p >>= (\x -> (q >>= r), falls x nicht in r vorkommt. 80. do-Notation (4 Punkte) Schreiben Sie p >>= q in do-Notation (ohne den Bindeoperator >>=). 81. Kaufmännisches Runden (5 Punkte) Schreiben Sie eine Funktion, die einen Gleitkommawert auf den nächstgelegenen Euround-Cent-Wert mit zwei Nachkommastellen rundet. Wenn die Eingabe genau in der Mitte zwischen zwei Cent-Beträgen liegt, dann soll das Ergebnis gewählt werden, dessen letzte Zier gerade ist. Beispiele: runde 0.325 = 0.32, runde 0.32501 = 0.33, runde 0.335 = 0.34, runde 0.31499 = 0.31, runde 0.315 = 0.32, runde 0.305 = 0.30. 82. Umnummerieren eines Baumes (10 Punkte) Schreiben Sie mit Hilfe der Zustandsmonade ein Programm nummeriere:: (Eq a) => Baum a -> Baum Int, das alle Daten in einem Baum durch die Zahlen 0,1,. . . ersetzt, wobei gleiche Daten durch die gleiche Zahl ersetzt werden sollen. Sie können ein Wörterbuch (Vorlesungen vom 2. und 4. 1. 2011) zu Hilfe nehmen. data Baum a = Leer | Knoten a (Baum a) (Baum a) (Vorlesung vom 16. 11. 2011) 83. Tilgungsplan (10 Punkte) (a) Sie haben am 1. 1. 2012 einen Kredit in Höhe k zu einem jährlichen Zinssatz p aufgenommen, den Sie durch unregelmäÿige Raten z1 , z2 , z3 , . . . zu Beginn eines jeden Jahres zurückzahlen. Schreiben Sie ein Programm zur Erstellung eines Tilgungsplanes. Die Ausgabe für [z1 , z2 ] = [100, 110] könnte zum Beispiel so aussehen: Datum Restschuld Zahlung Zinsen Tilgung 1.1.2012 1000.00 1.1.2013 950.00 100.00 50.00 50.00 1.1.2014 887.50 110.00 47.50 62.50 Dabei sollen alle Zwischenergebnisse kaufmännisch gerundet werden (siehe Aufgabe 81). (b) Erstellen Sie einen Tilgungsplan für regelmäÿige Raten in Höhe von z , bis der Kredit getilgt ist. Die letzte Rate müssen Sie unter Umständen reduzieren. 84. Zusatzaufgabe, 0 Punkte Bestimmen Sie die Rückzahlungsrate, die notwendig ist, um einen Kredit in a Jahren zu tilgen. 18 Funktionale Programmierung (ALP 1), WS 2011/12 13. Übungsblatt Test ab 6. Februar 2012 85. Aufzählen aller Möglichkeiten (10 Punkte) Schreiben Sie eine Funktion alleZerl:: [a]->[([a],[a])], die alle Zerlegungen ei- ner Liste in zwei Teillisten konstruiert; dabei sollen die Elemente in den Teillisten in derselben Reihenfolge vorkommen wie in der Eingabeliste. Zum Beispiel ist "cad") eine solche Zerlegung von "acbaadf". Bei einer Liste 2n Zerlegungen (die nicht alle verschieden sein müssen). n von ("abaf", Elementen gibt es 86. Zusatzaufgabe, 0 Punkte Unter welcher Bedingung an die Eingabeliste enthält die Ausgabe der vorigen Aufgabe 2n verschiedene Paare? 87. Permutationen (10 Punkte) Schreiben Sie ein Programm tionen der Zahlen 1, 2, . . . , n permutationen:: Int -> [[Int]], das alle n! Permuta- ausgibt. (Tipp: Es gibt zwei einfache Ansätze: Entweder man probiert alle Möglichkeiten für das erste Element durch, oder man versucht das Element n auf alle möglichen Arten in eine Permutation von 1, 2, . . . , n − 1 einzufügen.) 88. Syntaxanalyse von Ausdrücken (8 Punkte) Erweitern Sie das Programm aus der Vorlesung zum Parsen von Ausdrücken, sodass auch negative Konstanten erlaubt sind. 89. Zufallszahlen (15 Punkte) (a) Schreiben Sie ein Programm, das einen zufälligen Suchbaum mit indem es n zufällige Float-Zahlen n Knoten erzeugt, der Reihen nach in einen leeren Suchbaum ein- fügt. (Aufgabe 52 vom 8. Übungsblatt) (b) Erstellen Sie 1000 zufällige Suchbäume mit Suchbäume der Höhe h = 0, 1, 2, . . . n = 10 Knoten, und zählen Sie, wie oft herauskommen (Aufgabe 63 vom 9. Übungs- blatt). Bestimmen Sie den Mittelwert der Höhe. 90. Längste monotone Teilfolge (0 Punkte, freiwillig) Schreiben Sie ein Programm lmT:: Ord a => [a]->Int, das die Länge einer längsten [1,3,5] [2,1,3,4,3,6,5] (aber nicht die längste). streng monoton wachsende Teilfolge in einer Liste bestimmt. Zum Beispiel ist eine streng monoton wachsende Teilfolge vom 91. Der diskrete Fréchet-Abstand zur Ähnlichkeitsmessung zwischen zwei Polygonzügen (freiwillig, 0 Punkte) Schreiben Sie ein Programm für folgende Aufgabe. Wir stellen uns vor, dass ein Hund auf a1 , a2 , . . . , am von Punkten der Ebene wandert und sein Herrchen Folge b1 , b2 , . . . , bn . Dabei gelten folgende Regeln: einer gegebenen Folge auf einer gegebenen (a) Sie beginnen in den Punkten beziehungsweise bn a1 und b1 , und am Ende sind sie in den Punkten am angelangt. (b) Wenn der Hund im Punkt ai und das Herrchen im Punkt bj ist, dann haben sie folgende Möglichkeiten für den nächsten Schritt: ai+1 und das Herrchen bleibt auf bj . Der Hund bleibt auf ai und das Herrchen geht zu bj+1 . Sie bewegen sich beide gleichzeitig nach ai+1 beziehungsweise bj+1 . i. Der Hund geht nach ii. iii. Wie lang muss die Hundeleine mindestens sein, damit so ein Spaziergang möglich ist? 19 Funktionale Programmierung (ALP 1), WS 2011/12 14. Übungsblatt 92. Bäume kodieren und dekodieren (10 Punkte) (a) Geben Sie eine Beschreibung der Zeichenketten, die bei der Kodierung von Bäumen vom Typ Baum' Int gemäÿ Aufgabe 41 vom 6. Übungsblatt entstehen, in erweiterter Backus-Naur-Form (einschlieÿlich der Darstellung der Zahlen). data Baum' a = Blatt a | Knoten a (Baum' a) (Baum' a) (Sie können in Gedanken 'D' und 'U' mit '(' und ')' identizieren.) (b) (Aufgabe 49 vom 8. Übungsblatt, 0 Punkte, freiwillig) Schreiben Sie ein Programm, das die Umkehrfunktion zu Aufgabe 41 als Parse-Problem berechnet. 93. Aufzählen und Abzählen aller Möglichkeiten (15 Punkte) (a) Schreiben Sie ein Programm zur Erzeugung aller Suchbäume mit den Schlüsseln 1, . . . , n. (Die Werte sollen einfach auf 0 gesetzt werden.) (b) Zählen Sie, wie viele der Suchbäume mit den Schlüsseln 1, . . . , 10 die Höhe h = 0, 1, 2, . . . haben (vergleiche Aufgabe 63 vom 9. Übungsblatt und Aufgabe 89b vom 13. Übungsblatt). Bestimmen Sie den Mittelwert der Höhe. (Hinweis: Das Ergebnis muss nicht mit Aufgabe 89b übereinstimmen.) (c) (0 Punkte, freiwillig) Schreiben Sie ein möglichst ezientes Programm, das die Anzahl der Suchbäume mit den Schlüsseln 1, . . . , n berechnet. Wie groÿ muss n sein, damit die Anzahl gröÿer als 10100 wird? 94. Skalieren von Pixelgraken (Buchstabenbildern) (10 Punkte) Man kann rudimentäre Graken (vom Typ [String]) als Listen von Zeichenketten darstellen. (Die Graken von Aufgabe 38 vom 6. Übungsblatt kann man dann daraus durch die Standardfunktion unlines erzeugen.) (a) Schreiben Sie zwei Funktionen skaliereH, skaliereV:: Int -> [String] -> [String], die eine solche Grak in horizontaler beziehungsweise vertikaler Richtung um einen ganzzahligen Faktor k > 0 strecken (skalieren), indem die Zeichen k -mal wiederholt werden. Beispiel: skaliereH 3 ["D +-->", " D | ", " +--+ "] ! = ["DDD +++------>>>", " DDD ||| ", " +++------+++ "] ! (b) Schreiben Sie eine Funktion skaliere:: Int -> [String] -> [String], die eine Grak in beiden Richtungen skaliert. 95. Strukturelle Induktion (10 Punkte) Die Standardfunktionen takeWhile, dropWhile:: (a -> Bool) -> [a] -> [a] können so deniert werden: takeWhile p [ ] takeWhile p (x:xs) | | dropWhile p [ ] dropWhile p (x:xs) | | = [ ] p x = x : takeWhile p xs otherwise = [ ] = [ ] p x = dropWhile p xs otherwise = (x:xs) Leiten Sie daraus die Beziehung takeWhile p x ++ dropWhile p x = x her. 20 Algorithmen und Programmierung 1 (Funktionale Programmierung), WS 2011/2012 — Klausur Aufgabe 1 2 3 4 5 6 Punkte 20 15 20 20 5 10 gesamt: 90 90 Minuten. Abgabe bis Montag, 20. Februar 2012, 15:30 Uhr 1. (20 Punkte) Schreiben Sie ein Modul Stapel zur Implementierung des abstrakten Datentyps ST a, der einen Stapel (Keller, stack, pushdown storage) von Werten vom Typ a darstellt. Der Stapel soll folgenden Operationen erlauben: leer:: ST a -- erzeugt einen leeren Stapel push:: a -> ST a -> ST a -- fügt ein Element als oberstes ein top:: ST a -> a -- greift auf das oberste Element zu pop:: ST a -> ST a -- löscht das oberste Element vom Stapel istLeer:: ST a -> Bool -- testet, ob der Stapel leer ist Die Bedeutung der Operationen ist durch folgende Gleichungen gegeben. istLeer (leer) = True istLeer (push x s) = False top (push x s) = x pop (push x s) = s push (top s) (pop s) = s, falls not (istLeer s) Bei einem leeren Stapel (istLeer liefert True) soll top und pop eine Fehlermeldung ausgeben. Sie können frei entscheiden, welche Datenstruktur Sie zur Darstellung des Stapels verwenden und wie Sie die Operationen implementieren. Das Modul soll eine explizite Exportliste haben. Ist es erforderlich, a auf bestimmte Typklassen einzuschränken? (Diese müssen Sie eventuell bei den Signaturen der obigen Funktionen als Voraussetzungen ergänzen.) Begründen Sie Ihre Antwort. Bei allen Funktionen ist wie immer eine Typdeklaration anzugeben. 2. (15 Punkte) Welche Variablen kommen im Ausdruck λx. λx.λa.(ax(xx)yx) (λa.xa) gebunden vor? Welche Variablen kommen frei vor (bezogen auf den gesamten Ausdruck)? Reduzieren Sie den Ausdruck so weit wie möglich. 21 3. (20 Punkte) Summen Schreiben Sie ein Haskell-Programm, das in einer Liste vom Typ [Integer] ein Tripel (a, b, c) mit a+b = c findet, falls es eines gibt. Dabei müssen a, b und c von verschiedenen Stellen der Eingabeliste kommen. (Sie dürfen gleich sein, falls in der Eingabeliste gleiche Zahlen mehrfach vorkommen.) Sie dürfen die Funktion sort aus dem Modul Data.List verwenden, die eine Folge der Länge n mit Laufzeit O(n log n) sortiert. Verwenden Sie Kommentare zur Erläuterung Ihres Programms. Bei allen Funktionen ist wie immer eine Typdeklaration anzugeben. Analysieren Sie sie asymptotische Laufzeit Ihres Programms (in O-Notation in Abhängigkeit von der Länge n der Eingabeliste). (Falls Ihr Programm korrekt ist und eine bessere Laufzeit als O(n3 ) hat, gibt es bis zu 10 Zusatzpunkte.) 4. (20 Punkte) Welche Formel muss man für x einsetzen, damit die Gleichung drop m . take n = take (x) . drop m für alle m ≥ 0 und alle n ≥ 0 gilt? Beweisen Sie die Gleichung dann durch strukturelle Induktion (oder durch eine andere Methode Ihrer Wahl) unter Verwendung der folgenden Definitionen: (t1) (t2) (t3) (d1) (d2) (d3) take, drop:: Int -> [a] -> [a] take n _ | n <= 0 = [] take _ [] = [] take n (x:xs) = x : take (n-1) xs drop n xs | n <= 0 = xs drop _ [] = [] drop n (_:xs) = drop (n-1) xs 5. (5 Punkte) Funktionen höherer Ordnung Welcher der folgenden Ausdrücke ist äquivalent zur Formel [g x y | y <- ys]? a) (map . g x) ys, b) (map g x) ys, c) map(g x y) ys, d) map (g x)ys. (Es können auch mehrere Antworten richtig sein. Eine Begründung ist nicht erforderlich.) 6. (10 Punkte) Typinferenz Bestimmen Sie den allgemeinsten Typ, den die Funktion f haben kann. f a b c | b c = [c+2] | otherwise = a c Begründen Sie Schritt für Schritt, wie Sie zu Ihren Schlussfolgerungen kommen. 22