Fachrichtung 6.2 — Informatik Universität des Saarlandes Tutorenteam der Vorlesung Programmierung 1 Programmierung 1 (Wintersemester 2015/16) Aufgaben für die Übungsgruppen: 4 (Kapitel 4) Hinweis: Dieses Übungsblatt enthält von den Tutoren für die Übungsgruppe erstellte Aufgaben. Die Aufgaben und die damit abgedeckten Themenbereiche sind für die Klausur weder relevant noch irrelevant. 1 Einstieg in Listen Aufgabe 4.1 (Pattern Matching) Geben Sie an, welche der folgenden Ausdrücke auf die folgenden Muster passen, und welche Bindungen dabei erzeugt werden. Muster → ↓ Wert (2,4) ([2],[4]) [1,2,3] [1,3] [[]] [[3]] [(1,2)] ([],[]) ((),()) nil::nil (nil::nil)::nil nil::nil::nil (a,_) x [1,_] _::x::_ a::b (a::b)::c Aufgabe 4.2 Entscheiden Sie, ob die folgenden Ausdrücke wohlgetypt sind und geben Sie die Typen an. (a) nil (b) (2 :: nil) :: nil (c) [(true, 5), (false, 28)] (d) (nil :: nil) :: 1 :: nil :: nil :: nil (e) (nil :: nil :: nil) @ nil :: [[]] Aufgabe 4.3 Schreiben Sie eine Prozedur count: ’α → ’α list → int, die zählt, wie oft ein Element a in einer Liste enthalten ist. Nutzen Sie keine Hilfsprozeduren. Aufgabe 4.4 Schreiben Sie eine Prozedur body: α list → α list, welche die Liste ohne das letzte Element zurück gibt, erst mit und dann ohne die Hilfe von Listenprozeduren. Wenn die übergebene Liste leer ist, soll Empty geworfen werden. 1 Aufgabe 4.5 Schreiben Sie eine Prozedur truesum: (int * bool) list → int, welche eine Liste aus Paaren nimmt, und die Zahlen aus den Paaren, die als zweite Komponente true haben, aufaddiert und die restlichen außer Acht lässt. Verzichten Sie auf Konditionale. Aufgabe 4.6 Schreiben Sie eine Prozedur sEven: int list * int list → bool, die für ein Paar von Listen entscheidet, ob die erste Liste an Position 2 eine 7 und die zweite Liste an Position 1 eine gerade Zahl hat. Verallgemeinern Sie sEven, sodass kein Paar, sondern eine Liste von Listen als Eingabe genommen wird, wobei nur die ersten beiden Listen betrachtet werden. Hinweis: sEven’: int list list → bool. Aufgabe 4.7 Schreiben Sie eine Prozedur kubilist: int → int list, die eine Zahl k als Eingabe nimmt, und die Liste der Kubikzahlen von k bis 1 liefert. Für k ≤ 0 soll nil zurückgegeben werden. Für k = 3 soll das Ergebnis [27, 8, 1] lauten. Aufgabe 4.8 Schreiben Sie eine Prozedur doublemap: (α * β → γ) → α list → β list → γ list, die eine übergebene Prozedur f auf ein Tupel aus je einem Element der beiden übergebenen Listen anwendet. Sind die Listen unterschiedlich groß, soll die Ausnahme Subscript geworfen werden. Beispiel: doublemap f [2, 3] [true, false] = [f (2, true), f (3, false)] Aufgabe 4.9 Schreiben Sie eine Prozedur confuse: int list → int list, die zunächst prüft, ob eine Liste mindestens eine gerade Zahl enthält. Falls dem so ist, soll die Liste, die alle ungeraden Zahlen der Eingabeliste enthält, zurückgegeben werden. Andernfalls werden sämtliche Werte der Eingabeliste verdoppelt und die so entstandene Liste wird zurückgegeben. 2 Strings Aufgabe 4.10 Schreiben Sie eine Prozedur abc: string → int, die berechnet, wie oft in einem Eingabestring der String 00 abc00 enthalten ist. Aufgabe 4.11 Schreiben Sie eine Prozedur revi: string → string, die einen String bis auf das erste Zeichen reversiert. Zum Beispiel soll revi(Hallo) = Holla gelten. Handelt es sich um den leeren String oder besteht der String nur aus einem Zeichen, so soll die Prozedur divergieren. Sie dürfen Hilfsprozeduren verwenden. Aufgabe 4.12 Schreiben Sie eine Prozedur isord: string → bool, die für einen gegebenen String prüft, ob die einzelnen Zeichen innerhalb des Strings der lexikalischen Ordnung entsprechend geordnet sind. Aufgabe 4.13 Schreiben Sie eine Prozedur remove: char → string list → string list, welche alle Elemente einer Liste von Strings entfernt, in denen ein übergebenes Zeichen vorkommt. Überlegen Sie hierfür zunächst, welche Ihnen bekannten Prozeduren hilfreich sein könnten. Schreiben Sie nun mit Hilfe von remove eine Prozedur removea: string list → string list, die alle Elemente einer Liste entfernt, in denen ein #00 a00 vorkommt. 2 Aufgabe 4.14 Schreiben Sie eine Prozedur intlist: string → int list, die einen String, der eine Liste von positiven Zahlen nur durch Komma getrennt enthält, in diese Liste von Zahlen umschreibt. Aus 00 345, 786, 3200 wird [345,786,32]. 3 Faltung Aufgabe 4.15 Unterscheiden sich foldl op:: nil xs und foldr op:: nil xs? Aufgabe 4.16 Schreiben Sie eine Prozedur double: α list → α list, welche für eine gegebene Liste die Liste zurückgibt, in der jedes Element doppelt vorkommt. Aufgabe 4.17 Schreiben Sie eine Prozedur length’: α list list → int list, die eine Liste von Listen nimmt und eine Liste mit den Längen der Listen zurückgibt. Für [nil, [1, 2, 8], [5, 2]] lautet die Ausgabe [0, 3, 2]. Aufgabe 4.18 Schreiben Sie eine Prozedur minmax: int list → (int*int), die mit einmal Falten (insgesamt nur einem Aufruf von foldl bzw. foldr) die kleinste und die größte Zahl einer Liste zurückgibt. Für [3, 6, 2] lautet das Ergebnis (2, 6). Aufgabe 4.19 Schreiben Sie eine Prozedur evengreater: int list → bool, die für eine Liste von Zahlen entscheidet, ob sie mehr gerade als ungerade Zahlen enthält. Aufgabe 4.20 Schreiben Sie eine Prozedur zip : α list → β list → (α * β) list, die gleichlange Listen zu einer Liste wie aus dem Typschema ablesbar zusammenfügt. Es soll zip [1,2] [true,false] = [(1,true),(2,false)] gelten. Aufgabe 4.21 Schreiben Sie eine Prozedur primpro: int list → bool, die für eine Liste von Zahlen entscheidet, ob das Produkt der Primzahlen größer ist als die Summe der Nicht-Primzahlen. Eine Prozedur prim: int → bool, die sagt, ob eine Zahl eine Primzahl ist, sei gegeben. Aufgabe 4.22 Schreiben Sie eine Prozedur evensmaller: int list → int list list, die eine Liste von Zahlen nimmt und eine Liste zurückgibt, die zu jedem Element eine Liste mit allen geraden Zahlen zwischen 0 und diesem Element (jeweils exklusive) enthält. Für [3, 8, 7, 1] lautet die Ausgabe [[2], [2, 4, 6], [2, 4, 6], []]. Aufgabe 4.23 Schreiben Sie die Listenprozedur foldl mithilfe von iter. Sie dürfen dafür die Prozedur List.length: α list → int verwenden, die die Länge einer Liste liefert. Aufgabe 4.24 Schreiben Sie eine Prozedur map’: (α → β) → α list → β list, die map mithilfe von Faltung implementiert. Für (fn x ⇒ x div 2) [2, 5, 6, 9] liefert map und somit map’: [1, 2, 3, 4]. 3 Aufgabe 4.25 Schreiben Sie eine Prozedur counta: string list → (string * int) list, die eine Liste von Strings nimmt, diejenigen behält, die mindestens drei as enthalten, und ihnen die Anzahl von as zuordnet. Für ["abc","bcd","aaaaaz","b","ababa"] lautet die Ausgabe [("aaaaaz",5),("ababa",3)]. Aufgabe 4.26 Schreiben Sie eine Prozedur clean: string list → string, die eine nicht-leere Liste von Strings nimmt, den längsten String bestimmt und ihn um alle Ziffern bereinigt zurückgibt. Für ["abc2","bc1d","a22a3aaaz","b","a1baba"] lautet die Ausgabe "aaaaaz". Aufgabe 4.27 Schreiben Sie eine Prozedur thegreatest: int list list → int, die für eine Liste von nicht-leeren Listen von positiven Zahlen entscheidet, die wievielte Liste von Zahlen die insgesamt größte Zahl enthält. Für [[2, 3, 0], [5], [3, 5, 3, 1]] soll 1 geliefert werden. Für eine leere Liste von Listen soll die Ausnahme Empty geworfen werden. Hinweis: Int.max : int * int → int liefert die größere zweier Zahlen. Aufgabe 4.28 Schreiben Sie eine Prozedur power: α list → α list list, die ähnlich zur Potenzmenge die Liste aller Teillisten einer Eingabeliste liefert. Für [1,2,2] soll die Ausgabeliste folgende Listen enthalten: [], [1], [2], [2], [1,2], [1,2], [2,2], [1,2,2]. 4 Programmierung – eine Einführung in die Informatik mit Dieter Schlau Aufgabe 4.29 (Einmal Falten, bitte!) Schreiben Sie eine nichtrekursive Prozedur magic : real list → real list mittels einer Benutzung von Faltung, die eine Liste von Werten nimmt und eine Liste der Differenzen dieser Werte zum Durchschnittswert der Liste zurückgibt. Es soll also gelten: magic [1.0,2.0,3.0] = [∼1.0,0.0,1.0]. Benutzen Sie keine der bekannten Listenprozeduren (außer genau einmal Faltung). Sie dürfen Real.fromInt verwenden. 4