IS S SA R 5. Übungsblatt zu Programmierung, WS 04/05 S UN E R SIT A IV A VIE N Prof. Dr. Gert Smolka, Dipl.-Inform. Guido Tack http://www.ps.uni-sb.de/courses/prog-ws04/ Lesen Sie im Skript: Kapitel 5 Aufgabe 5.1 Gegeben sei der Typ shape aus Absatz 5.1 im Skript. Deklarieren Sie eine Prozedur variant : shape → int, die die Variantenummer eines geometrischen Objekts liefert. Beispielsweise soll variant(Square 3.0) = 2 gelten. Aufgabe 5.2 Deklarieren Sie eine Prozedur scale : real → shape → shape, die ein Objekt gemäß einem Faktor skaliert (d.h. vergrößert oder verkleinert). Beispielsweise soll scale 0.5 (Square 3.0) = Square 1.5 gelten. Aufgabe 5.3 Schreiben Sie eine Prozedur test : int → bool, die testet, ob das Quadrat einer ganzen Zahl im darstellbaren Zahlbereich liegt. Aufgabe 5.4 Führen Sie zweistellige Sequenzialisierungen (e1 ; e2 ) auf Abstraktionen und Applikationen zurück. Aufgabe 5.5 Die Prozedur testDouble aus Abschnitt 5.4.4 im Skript testet auch sehr lange Listen schnell auf Doppelauftreten. Schreiben Sie einen Test auf Doppelauftreten, der ohne Sortieren arbeitet, und überzeugen Sie sich mit der Liste [1, . . . , 10000] davon, dass testDouble sehr viel schneller ist. Daran ändert sich auch nichts, wenn Sie statt Listsort.sort eine selbstgeschriebene Sortierprozedur verwenden, die durch Mischen sortiert. Aufgabe 5.6 Deklarieren Sie eine Prozedur vars : exp → var list, die zu einem Ausdruck (siehe Abschnitt 5.5 im Skript) eine Liste liefert, die die in dem Ausdruck vorkommenden Variablen enthält. Orientieren Sie sich an der Prozedur subexps. Aufgabe 5.7 Deklarieren Sie eine Prozedur count : var → exp → int, die zählt, wie oft eine Variable in einem Ausdruck auftritt. Beispielsweise tritt x in x + x zweimal auf. Aufgabe 5.8 Deklarieren Sie eine Prozedur check : exp → exp → bool, die für zwei Ausdrücke e und e0 testet, ob e ein Teilausdruck von e0 ist. 2004–11–17 11:52 Aufgabe 5.9 Schreiben Sie eine Prozedur instantiate : env → exp → exp, die zu einer Umgebung V und einem Ausdruck e den Ausdruck liefert, den man aus e erhält, indem man die in e vorkommenden Variablen gemäß V durch Konstanten ersetzt. Beispielsweise soll zu der Umgebung val env = fn 1 => 5 | 2 => 3 | _ => raise Unbound und dem Ausdruck A(V 1, V 2) der Ausdruck A(C 5, C 3) geliefert werden. Orientieren Sie sich an der Prozedur eval. Aufgabe 5.10 (Symbolisches Differenzieren) Sie sollen eine Prozedur schreiben, die Ausdrücke nach der Variable x ableitet. Hier ist ein Beispiel: (x 3 + 3x 2 + x + 2)0 = 3x 2 + 6x + 1 Ausdrücke sollen gemäß dem folgenden Typ dargestellt werden: datatype exp = | | | | C X A M P of int c x u+v u·v un of exp * exp of exp * exp of exp * int a) Schreiben Sie eine Deklaration, die den Bezeichner u an die Darstellung des Ausdrucks x 3 + 3x 2 + x + 2 bindet. Der Operator + soll nach links gruppieren. b) Schreiben Sie eine Prozedur derive : exp → exp, die die Ableitung eines Ausdrucks gemäß den folgenden Regeln berechnet: c0 = 0 x 0 = 1 (u + v) 0 = u0 + v 0 (u · v)0 (un )0 = u0 · v + u · v 0 = n · un−1 · u0 Die Ableitung darf vereinfachbare Teilausdrücke enthalten (z.B. 0 · u). c) Schreiben Sie eine Prozedur simplifyTop : exp → exp, die versucht, einen Ausdruck auf oberster Ebene durch die Anwendung einer der folgenden Regeln zu vereinfachen: 0+u → u u+0 → u 0·u → 0 u·0 → 0 1·u → u u·1 → u u0 → 1 u1 → u 2004–11–17 11:52 Wenn keine der Regeln auf oberster Ebene anwendbar ist, soll der Ausdruck unverändert zurückgeliefert werden. d) Schreiben Sie eine Prozedur simplify : exp → exp, die einen Ausdruck gemäß der obigen Regeln solange vereinfacht, bis keine Regel mehr anwendbar ist. Gehen Sie bei zusammengesetzten Ausdrücken wie folgt vor: i) Vereinfachen Sie zuerst die Komponenten. ii) Vereinfachen Sie dann den Ausdruck mit den vereinfachten Komponenten mithilfe von simplifyTop. Aufgabe 5.11 (Konstruktordarstellung der natürlichen Zahlen) In dieser Aufgabe stellen wir die natürlichen Zahlen mit den Werten des Typs datatype nat = O | S of nat wie folgt dar: 0 7→ O, 1 7→ S O, 2 7→ S(S O), 3 7→ S(S(S O)), und so weiter. a) Deklarieren Sie eine Prozedur rep : int → nat, die die Darstellung einer natürlichen Zahl liefert. b) Deklarieren Sie eine Prozedur num : nat → int, die zu einer Darstellung die dargestellte Zahl liefert. c) Deklarieren Sie für nat kaskadierte Prozeduren add, mul und less, die den Operationen +, ∗ und < für natürliche Zahlen entsprechen. Verwenden Sie dabei keine Operationen für int. Aufgabe 5.12 Beantworten Sie die folgenden Fragen: a) Wieviele Knoten, die keinen Vater haben, hat ein Baum? Wie heißen diese Knoten? b) Kann ein Baum Knoten haben, zu denen mehr als eine Kante führt? c) Gibt es einen Baum, in dem es ein Blatt gibt, zu dem es von der Wurzel aus mehr als einen Pfad gibt? Aufgabe 5.13 Sei t ein Baum mit n ≥ 1 Kanten. a) b) c) d) Welche Größe hat t mindestens/höchstens? Wie viele Blätter hat t mindestens/höchstens? Wie viele innere Knoten hat t mindestens/höchstens? Welche Tiefe hat t mindestens/höchstens? Aufgabe 5.14 Schreiben Sie eine Prozedur binary : α tree → bool, die testet, ob ein Baum binär ist. Aufgabe 5.15 (Teilausdrücke) Die arithmetischen Ausdrücke aus Abschnitt 5.5 im Skript kann man als binäre Bäume auffassen. Dabei liefern die Konstruktoren C und 2004–11–17 11:52 V atomare und die Konstruktoren A und M zusammengesetzte Bäume. Schreiben Sie eine Prozedur subexp : exp → int list → exp, die zu einem Ausdruck und einer Adresse den entsprechenden Teilausdruck liefert. Für ungültige Adressen soll die Ausnahme Subscript geliefert werden. Aufgabe 5.16 Schreiben Sie eine Prozedur tree : int → int tree, die zu n ≥ 0 einen balancierten Binärbaum der Tiefe n liefert, dessen Knoten gemäß der Tiefe der ihnen zugeordneten Teilbäume markiert sind. Für n = 2 soll tree den Baum 2 1 1 0 0 0 0 liefern. Achten Sie darauf, dass die jeweils identischen Unterbäume eines Teilbaums jeweils nur einmal berechnet werden. Das sorgt dafür, dass ihre Prozedur auch für n = 1000 schnell ein Ergebnis liefert. Aufgabe 5.17 Schreiben Sie eine Prozedur breadth : int tree → int, die die Breite eines Baums liefert. Aufgabe 5.18 Schreiben Sie eine Prozedur sum : int tree → int, die die Summe aller Marken eines Baums liefert. Wenn eine Marke mehrfach auftritt, soll sie auch mehrfach in die Summe eingehen. Aufgabe 5.19 Schreiben Sie eine Prozedur map : (α → β) → α tree → β tree, die eine Prozedur auf alle Marken eines Baums anwendet. Aufgabe 5.20 Schreiben Sie eine Prozedur forall : (α → bool) → α tree → bool, die testet, ob eine Prozedur für alle Marken eines Baums true liefert. 2004–11–17 11:52