Prof. Dr. Manfred Schmidt-Schauß Künstliche Intelligenz/Softwaretechnologie Fachbereich Informatik und Mathematik/ Institut für Informatik Johann Wolfgang Goethe-Universität Frankfurt am Main Grundlagen der Programmierung 2 Sommersemester 2008 Aufgabenblatt Nr. 7 Abgabe: Mittwoch 28. Mai 2008 vor! der Vorlesung Bitte beachten Sie, dass zu Ihrer Lösung zugehöriger Quellcode sowohl gedruckt abgegeben als auch per Email an den entsprechenden Tutor gesendet werden muss!. Für zu implementierende Programme/Funktionen sind stets auch Testaufrufe mit geeigneten Werten der Lösung beizufügen! Aufgabe 1 (15 Punkte) a) Üben Sie die Benutzung des Haskell-Interpreters GHCi, indem Sie den Interpreter starten (bzw. eventuell vorher installieren) und sich mit der zugehörigen Dokumentation vertraut machen. Machen Sie sich insbesondere mit den Kommandos des Interpreters vertraut und erklären Sie die Funktionalitäten der Kommandos1 :load, :reload, :cd, :quit und :? und geben Sie Beispiele für deren Verwendung an. (5 Punkte) b) Implementieren Sie eine Funktion in Haskell, die vier Parameter als Eingaben erwartet: – eine Gesamtzahl an Übungspunkten aus der ersten Hälfte, – eine Gesamtzahl an Übungspunkten aus der zweiten Hälfte, – einen Wahrheitswert der genau dann wahr (True) ist, wenn mindestens einmal in der ersten Hälfte der Übungen vorgerechnet wurde, und – einen Wahrheitswert der genau dann wahr (True) ist, wenn mindestens einmal in der zweiten Hälfte der Übungen vorgerechnet wurde. Als Ausgabe soll die Funktion die Bonuspunkte für die Klausur berechnen. Speichern Sie die Funktion in einer Datei2 und laden Sie sie in einen Haskell-Interpreter. Testen Sie die Funktion anschließend mit sinnvollen Werten. (10 Punkte) Aufgabe 2 (20 Punkte) Implementieren Sie in Haskell eine rekursive Funktion, die die Quersumme3 einer natürlichen Zahl berechnet. Hinweise: • In Haskell sind die Operatoren div und mod zur ganzzahligen Division mit Rest bereits definiert. Hierbei berechnet div den ganzzahligen Anteil und mod den Rest einer solchen Division. • Präfix-Operatoren wie z. B. div können in Haskell auch infix verwendet werden, indem sie in Hochkommas eingeschlossen werden. Z. B. kann (div 9 3) auch als (9 ‘div‘ 3) geschrieben werden. Infix-Operatoren wie z. B. + können in Haskell auch präfix verwendet werden, indem sie in Klammern gesetzt werden. Z.B. kann (3 + 5) auch als (+) 3 5 geschrieben werden. 1 Man kann die Kommandos auch verkürzt eingeben, d.h. z.B. :l statt :load Haskell-Quelldateien haben die Endung .hs bzw. .lhs, wenn Sie den Literate Haskell-Stil verwenden 3 Die Quersumme einer Zahl ist die Summe ihrer Ziffern. 2 1 Aufgabe 3 (20 Punkte) Bei der Multiplikation, Division, Addition oder Subtraktion zweier ganzer Zahlen kann das Ergebnis mithilfe des Neunertests auf Richtigkeit hin überprüft werden. Hierbei berechnet man jeweils die Quersummen der Ausgangszahlen und des Ergebnisses und wiederholt dieses solange für jede der entstehenden Zahlen, bis die entstehenden Quersummen einstellige Zahlen sind. Anschließend rechnet man die Zahlen noch modulo 9, d.h. Neunen werden zu Nullen. Die Rechnung war (wahrscheinlich) richtig, wenn die beiden Reste der Ausgangszahlen miteinander verknüpft (modulo 9) denselben Rest ergeben wie die Quersumme des Ergebnisses. Wir betrachten als Beispiel: 9999 + 8888 = 18887. Dann berechnet der Neunertest: • für 9999: 9+9+9+9 = 36, 3+6 = 9 und 9 modulo 9 = 0 • für 8888: 8+8+8+8 = 32, 3+2 = 5 und 5 modulo 9 = 5 • für 18887: 1+8+8+8+7 = 32, 3+2 = 5 und 5 modulo 9 = 5 Da 0 + 5 = 5, war die Rechnung wahrscheinlich richtig. Implementieren Sie in Haskell eine Funktion neunertest, die vier Parameter erwartet: • eine binäre Rechenoperation auf Zahlen, wie (+), (-), (*) und (/), • zwei Eingabezahlen der Rechenoperation und • ein Ergebnis der Rechenoperation. Die Funktion soll nun den Neunertest anhand der Eingaben durchführen und als Ergebnis True liefern, wenn der Neunertest erfolgreich war; andernfalls sollte sie False liefern. Aufgabe 4 (25 Punkte) Es seien folgende Funktionsdefinitionen in Haskell gegeben: f1 f2 f3 f4 a) b) c) d) e) a a a a b b b b = = = = (f1 a (b+1)) ‘mod‘ (f3 a b) if (f2 (a+3) (b-2)) > (f3 100 b) then f1 (a-1) (b+1) else f2 (a+1) (b-1) if a+b > 1000 then 20 else f4 a (b*3) (f3 (a+4) (b-10)) + (f1 (a-1) (b+2)) Für welche Funktionen f, g ∈ {f1, f2, f3, f4} gilt f referenziert g direkt? Für welche Funktionen f , g ∈ {f1, f2, f3, f4} gilt f referenziert g? Welche der Funktionen f1, f2, f3 und f4 sind direkt rekursiv? Welche der Funktionen f1, f2, f3 und f4 sind rekursiv? Welche Paare der Funktionen f1, f2, f3 und f4 sind verschränkt rekursiv? (7 (6 (3 (4 (5 Punkte) Punkte) Punkte) Punkte) Punkte) Aufgabe 5 (20 Punkte) Seien f und g definiert als f x y = 2 + (g x) g z = if z >= 20 then 1 else f (4*z) (2+z) Werten Sie den Ausdruck f (1+(3*3)) (g (5*5)) per Hand in applikativer Reihenfolge aus. Geben Sie sämtliche Reduktionsschritte sowie die jeweils verwendete Regel als Buchstabe d, i oder a an, wobei d: Definitionseinsetzung (δ-Reduktion) i: Auswertung einer Fallunterscheidung (if-Reduktion) a: Auswertung von arithmetischen Ausdrücken 2