5. Übungsblatt zu Programmierung, WS 04/05

Werbung
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
Herunterladen