pue08

December 9, 2016

1 1.1

Aufgabe 1: Ein einfaches Zeichenprogramm a)

Erstellen Sie eine Klasse Square mit den folgenden Eigenschaften: Objektvariablen: - width: Seitenlänge (default: 0) - color: Füllfarbe (ein einzelnes Zeichen, default: ’*’) Klassenvariablen: - shape_type: Name der repräsentierten Form (default: "Square") Objektmethoden: - __init__(self,w,c): Konstruktor mit der Seitenlänge und der Farbe als Parameter - draw(self): Zeichne das Quadrat, indem es auf der Konsole ausgegeben wird. - Beispiel für ein 3x3 Quadrat mit Farbe ’*’: *** *** *** (Anmerkung: Man denke sich, dass die obige Form quadratisch aussähe) - scale(self,factor): Skaliere Quadrat um ganzzahligen Faktor In [ ]: # Definition der Klasse "Square"

1.2

b)

Testen Sie Ihre Klasse Square 1. Erstellen Sie zwei Quadrate q1 (Seitenlänge 4) und q2 (Seitenlänge 6). 2. Geben Sie beide Quadrate mithilfe der Objektmethode draw aus. 3. Setzen Sie die Seitenlänge von q1 gleich mit der Seitenlänge von q2 und geben Sie q1 aus. 4. Skalieren Sie q1 um den Faktor 2 und geben Sie es aus. 5. Geben Sie den Shape-Typ von q1 aus. In [ ]: # Test der Klasse "Square"

1.3

c)

Erstellen Sie eine Klasse Rectangle mit den folgenden Eigenschaften: Objektvariablen: - width: Breite des Rechtecks (default: 0) - height: Höhe des Rechtecks (default: 0) - color: Füllfarbe (ein einzelnes Zeichen, default: ’*’) Klassenvariablen: - shape_type: Name der repräsentierten Form (Default: "Rectangle") Objektmethoden: - __init__(self,w,h,c): Konstruktor der beide Seitenlängen und die Farbe setzt. - draw(self): Zeichne das Rechteck, indem es auf der Konsole ausgegeben wird. - Beispiel für ein 5x3 Rechteck mit Farbe ‘#’: ##### ##### ##### scale(self,factor): Skaliere nur die Breite um einen ganzzahligen Faktor In [ ]: # Definition der Klasse "Rectangle"

1

1.4

d)

Testen Sie Ihre Klasse Rectangle : 1. Erstellen Sie zwei Rechtecke r1 (Breite: 4, Höhe: 3) und r2 (Breite: 6, Höhe: 3). 2. Geben Sie beide Rechtecke mithilfe der Objektmethode draw aus. 3. Setzen Sie Breite und Höhe von r1 gleich denen von r2 und geben Sie r1 aus. 4. Skalieren Sie r1 um den Faktor 2 und geben Sie es aus. 5. Geben Sie den Shape-Typ von r1 aus. In [ ]: # Testen der Klasse Rechteck

2 2.1

Aufgabe 2: Vererbung einfach a)

Betrachten Sie Ihre Implementierung aus Aufgabe 1: - An welchen Stellen haben Sie semantisch identischen Code stehen? - Ist ihre Implementierung einfach auf beliebig viele verschiedene Formen erweiterbar?

2.2

b)

Zunächst stellen wir eine einfache Vererbungshierarchie her: 1. Kopieren Sie ihre Definitionen der Klassen Square und Rectangle in die untere Zelle. 2. Benennen Sie die Klassen in OOP_Square bzw. OOP_Rectangle um (den Wert des Attributs shape_type können Sie unverändert lassen). 3. Definieren Sie eine Klasse OOP_Shape als Basisklasse für beliebige geometrische Formen. 4. Lassen Sie die Klassen OOP_Square und OOP_Rectangle von OOP_Shape erben. 5. Werden Sie redundante Code-Abschnitte los, indem Sie sie als Methoden der Basisklasse OOP_Shape implementieren (und anschließend aus den Unterklassen entfernen). Wichtig: Überlegen Sie sich gut, welche Klasse welche Methoden implementieren sollte. Hat z.B. jede beliebige geometrische Form eine Breite und Höhe? In [ ]: # Definition der Klasse OOP_Shape

# Definition der Klasse OOP_Square

# Definition der Klasse OOP_Rectangle

2.3

c)

Testen Sie ihre Implementierung, indem Sie die Schritte aus Aufgabe 1b und 1d ausführen. Hat sich etwas geändert im Vergleich zu Aufgabe 1? In [ ]: # Testen der Implementierung

3 3.1

Aufgabe 3: Einige Modifikationen a)

Kopieren Sie ihre Klassendefinitionen aus Aufgabe 2 in die Zelle unten. 2

3.2

b)

Überschreiben Sie die Methode scale(self,factor) der Klasse OOP_Rectangle, sodass sowohl Breite als auch Höhe des Rechtecks skaliert werden.

3.3

c)

In der Vorlesung haben Sie gelernt, wie Sie eine formatierte Ausgabe von Objekten erreichen können indem Sie eine Objektmethode mit einem bestimmten Namen implementieren. Erweitern Sie ihre Klassen insofern, dass die Anweisung print(q1) die Ausgabe “Quadrat mit Breite 4” und die Anweisung print(r1) die Ausgabe “Rechteck mit Breite 4 und Höhe 3” erzeugt. In [ ]: # Definition der Klasse OOP_Shape # Definition der Klasse OOP_Quadrat # Definition der Klasse OOP_Rectangle

# Testen der Implementierung q1 = Square(4) r1 = Rectangle(2,3) print(q1) print(r1)

4 4.1

Aufgabe 4: Traversieren eines Binärbaums a)

Betrachten Sie die in der unteren Codezelle enthaltene Implementierung eines Binärbaums: - Wofür ist die die Klasse TreeNode da? - Warum reicht die kurze Definition der Klasse BinaryTree aus um einen beliebig großen Binärbaum zu erstellen? Welche Rolle spielt TreeNode hierbei? - Inwiefern unterscheiden sich die beiden Konstruktoren von den in der Vorlesung vorgestellten? Welches Paradigma wird hier verwendet?

4.2

b)

Erstellen Sie in der unteren Zelle den folgenden Binärbaum und weisen Sie ihn einer Variable namens tree zu. Die Zahlen in den Knoten stellen die key Werte dar. Als values können Sie beliebige Werte speichern (Strings, Zahlen, Listen, etc.).

3

Tipp: Der Teilbaum bestehend aus den Knoten 2, 7 und 5 könnte wie folgt konstruiert werden: tree = BinaryTree( TreeNode(8,"abc", TreeNode(3,100), TreeNode(10,30.0)))

4.3

c)

Implementieren Sie die rekursive Methode inOrderTraverse(self), welche den in Teilaufgabe b) erstellen Binärbaum “in-order” traversiert und die Werte der einzelnen Knoten ausgibt. Überlegen Sie sich dazu zunächst, welchen Zustand Sie sich in jeder Rekursionsstufe merken müssen. Die erwartete Ausgabe ist: 1 3 4 (mehr Informationen zu verschiedenen Traversierungsvarianten finden Sie z.B. hier: https://en.wikipedia.org/wiki/Tree_traversal).

4.4

d)

Erweitern Sie Ihre Implementierung insofern, dass print(tree) die obige Ausgabe erzeugt.

4.5

e) (Zusatzaufgabe)

Implementieren Sie nach demselben Schema wie in preOrderTraverse(self) und postOrderTraverse(self).

4.6

c)

die

Methoden

f) (Zusatzaufgabe)

Implementieren Sie die Methode traverse(self, traversal_type), die anhand des Parameters traversal_type zwischen den verschiedenen Varianten unterscheidet, welche angewandt werden soll. 4

In [11]: class TreeNode: def __init__(self, key, val, lc = None, rc = None): self.key = key self.value = val self.leftChild = lc self.rightChild = rc def isLeaf(self): return ((self.leftChild is None) and (self.rightChild is None)) def inOrderTraverse(self): # Your code here (c) pass class BinaryTree: def __init__(self, r=None): self.root = r def inOrderTraverse(self): # Your code here (c) pass # Binärbaum erstellen (b) # Baum traversieren und ausgeben (c) # Baum ausgeben mit print (d) #print(tree)

5

Aufgabe 5 (Zusatzaufgabe): Dreieck implementieren

Nutzen Sie Ihren Code aus Aufgabe 2 bzw. 3 und implementieren Sie die Klasse OOP_Triangle. Überlegen Sie sich dabei selbst, welche Methoden und Attribute diese haben sollte und inwieweit Sie ihre Implementierung aus Aufgabe 3 erweitern müssen. Testen Sie anschließend Ihre Implementierung wie in den vorangegangenen Aufgaben. In [ ]:

5