Montag, 25. November 2013
Java Forever And Ever Movie (JAVA vs Windows .Net)
Montag, 18. November 2013
Musterlösung Römische Zahlen umwandeln (POS1: 2BHIF)
Mögliche Lösung zu Römische Zahlen umwandeln (POS1: 2BHIF).
Die Klasse könnte folgendermaßen programmiert werden. Das Dictionary enthält die möglichen "Ziffern" (unter Hochkomma, da bestimmte Ziffernkombinationen, wie zum Beispiel "IX", als eine Ziffer gelten). Zur Umrechnung müssen die Werte absteigend sortiert werden, damit die richtige "Ziffer" (z.B. "IX" für 9) verwendet wird.
Bei der Umrechnung in römische Zahlen wird der Reihe nach von der größten zur kleinsten "Ziffer" (daher absteigend sortiert) probiert, ob der Wert enthalten ist. Ist das der Fall, dann wird die "Ziffer" an den String angehängt und der entsprechende Wert von der Zahl abgezogen. Zum Beispiel 1999
1999 M 999 IM 0 ferigoder 392
392 C 292 C 192 C 92 XC 2 I 1 I 0 fertig
Bei der umgekehrten Umrechnung wird der Reihe nach probiert, ob am Beginn der römischen Zahl eine bestimmte "Ziffer" vorkommt. Ist dies der Fall, so wird der entsprechende Wert zum Ergebnis dazugezählt. Mit einem Zähler wird geprüft, dass keine Ziffer mehr als drei mal vorkommt. Zum Beispiel CCCXCII
CCCXCII 100 (C) CCXCII 200 (C) CXCII 300 (C) XCII 390 (XC) II 391 (I) I 392 (I)
Zum Testen wird einfach eine Liste von Zahlen verwendet, die in römische Zahlen und wieder zurück gerechnet werden. Ungültige Zahlen liefern eine Exception, die bei einem entsprechenden Testfall kommen muss:
# test value error try: ra = RomanNumber("VIIII") assert(False) except ValueError: pass
Die gesamte Klasse könnte also so aussehen:
#!/usr/bin/env python3 """ File: RomanNumber.py Desc: class for roman numbers Created: 2013-11-18, Harald R. Haberstroh """ class RomanNumber: """Roman numbers. Internal representation is always the integer value. This implementation stores both values (integer and roman). """ digits = { "I":1, "V":5, "X":10, "L":50, "C":100, "D":500, "M":1000, "IV":4, "IX":9, "XL":40, "XC":90, "CD":400, "CM":900} keys = list(digits.items()) keys.sort(key=lambda x: -x[1]) def __init__(self, value): """Initialize with value. If type of value is int, than this is the integer value. If type of value is str, than this is a roman number, which has to be converted into the internal int-value""" if type(value) is str: self.roman = value self.intval = self.__toInt(value) else: self.intval = value self.roman = self.__toRoman(value) def toRoman(self): """returns string with roman representation""" return self.roman def toInt(self): """returns integer value of roman number""" return self.intval def add(self, other): """add the value of other (RomanNumber) to own (self) value and return a new RomanNumber object.""" return RomanNumber(self.intval + other.toInt()) def sub(self, other): """subtract the value of other (RomanNumber) from own (self) value and return a new RomanNumber object.""" return RomanNumber(self.intval - other.toInt()) def mul(self, other): """multiply the value of other (RomanNumber) with own (self) value and return a new RomanNumber object.""" return RomanNumber(self.intval * other.toInt()) def div(self, other): """divide (integer division) own value by the value of other value and return a new RomanNumber object.""" return RomanNumber(self.intval // other.toInt()) def __str__(self): """returns the same value as toRoman(self)""" return "%s (%d)" % (self.roman, self.intval) def __toRoman(self, intval): romval = "" for digit, val in self.keys: while intval >= val: romval += digit intval -= val return romval def __toInt(self, romval): roman = romval.upper() intval = 0 for digit, val in self.keys: cntDigit = 0 # count same group while roman.startswith(digit): intval += val roman = roman[len(digit):] cntDigit += 1 if cntDigit >= 4: raise ValueError() return intval if __name__ == '__main__': zahlen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 32, 43, 48, 49, 54, 65, 76, 87, 98, 99, 100, 201, 302, 403, 491, 499, 504, 605, 706, 807, 908, 999, 1001, 1279, 1331, 1496, 1883, 1949, 1967, 1990, 1999, 2006, 2013] for f in zahlen: rn = RomanNumber(f) # print('%4d: %20s - %4d' % (f, rn.toRoman(), rn.toInt())) assert(f == rn.toInt()) for i in range(len(zahlen) // 2): ra = RomanNumber(zahlen[i]) rb = RomanNumber(zahlen[-i]) rc = ra.add(rb) print(ra, "+", rb, "=", rc) assert(zahlen[i] + zahlen[-i] == rc.toInt()) rc = rb.sub(ra) print(rb, "-", ra, "=", rc) assert(zahlen[-i] - zahlen[i] == rc.toInt()) for i in range(len(zahlen) // 8): ra = RomanNumber(zahlen[i]) rb = RomanNumber(zahlen[len(zahlen) // 2 - i]) rc = ra.mul(rb) print(ra, "*", rb, "=", rc) assert(zahlen[i] * zahlen[len(zahlen) // 2 - i] == rc.toInt()) # test value error try: ra = RomanNumber("VIIII") assert(False) except ValueError: pass print("all tests passed")
Beim romancalc.py
wird jeder Schritt mit einem try - except
- Block umgeben, um die Fehler- und Sonderfälle zu behandeln.
Eine Spezialität ist der Aufruf des entsprechenden Operators. Hier wird ein Dictionary mit den möglichen Operationen verwendet, wobei der Aufruf als Funktion und nicht als Methode stattfindet (der erste Parameter self
enthält ja das Objekt, welches dann explizit mit übergeben wird).
Das gesamte Modul könnte wie folgt aussehen:
#!/usr/bin/env python3 """ File: romancalc.py Desc: simple caluculator for roman numbers, using RomanNumber Created: 2013-11-18, Harald R. Haberstroh """ from RomanNumber import RomanNumber import sys operators = { "+":RomanNumber.add, "-":RomanNumber.sub, "*":RomanNumber.mul, "/":RomanNumber.div } while True: try: line = input(">>> ") except EOFError: break try: a, op, b = line.split() except ValueError: print("syntax error", file=sys.stderr) continue if a.isdigit(): a = int(a) if b.isdigit(): b = int(b) try: ra = RomanNumber(a) rb = RomanNumber(b) except ValueError: print("invalid roman number", file=sys.stderr) continue try: rc = operators[op](ra, rb) print(ra, op, rb, "=", rc) except KeyError: print("invalid operator '%s'" % (op), file=sys.stderr)
Labels: Aufgabe, Lösung, POS1-2, Python
Römische Zahlen umwandeln (POS1: 2BHIF)
Römische Zahlen
Schreiben Sie eine Klasse RomanNumber
, welche es erlaubt, mit römischen Zahlen zu rechnen bzw. römische Zahlen in ganze Zahlen und umgekehrt umzurechnen. Schreiben Sie dazu Methoden zum Umrechnen von ganzen Zahlen (1 bis 3000) in Römische Zahlen und umgekehrt. Die römischen Ziffern haben folgende Bedeutung:
I ... 1 V ... 5 X ... 10 L ... 50 C ... 100 D ... 500 M ... 1000Beachten Sie, dass nur jeweils drei gleiche Ziffern hintereinander geschrieben werden. Stattdessen wird die nächst größere Einheit benutzt und eine Einheit abgezogen (XC = 90, XCIX = 99, IX = 9, VIII = 8).
class RomanNumber: """Roman numbers. Internal representation is always the integer value. """ def __init__(self, value): """Initialize with value. If type of value is int, than this is the integer value. If type of value is str, than this is a roman number, which has to be converted into the internal int-value""" pass def toRoman(self): """returns string with roman representation""" pass def toInt(self): """returns integer value of roman number""" pass def add(self, other): """add the value of other (RomanNumber) to own (self) value and return a new RomanNumber object.""" pass def sub(self, other): """subtract the value of other (RomanNumber) from own (self) value and return a new RomanNumber object.""" pass def mul(self, other): """multiply the value of other (RomanNumber) with own (self) value and return a new RomanNumber object.""" pass def __str__(self): """returns the value like 'XXII (23)'""" pass
Ergänzen Sie dieses Gerüst zu einer funktionierenden Klasse und schreiben Sie ein Testprogramm mit fix programmierten Testfällen.
Schreiben Sie weiters ein zweites Modul, welches die Klasse RomanNumber
importiert und jeweils eine Zeile der Art
zahl op zahleinliest, die Operation
op
(+
, -
oder *
) ausführt und das Ergebnis ganzzahlig und als Römische Zahl ausgibt. zahl
ist jeweils eine ganze Zahl oder eine römische Zahl.
Beispielaufrufe:
~/work/tmp > python romancalc.py >>> 24 + 27 LI (51) >>> LI - 24 XXVII (27) >>> LI - XXIV XXVII (27) >>> ~/work/tmp >
Informationen finden Sie unter:
Labels: Aufgabe, POS1-2, Python, Testen
Mittwoch, 13. November 2013
Einführung Objektorientiertes Programmieren (POS1: 2BHIF)
Es folgt ein Beispiel:
Aufgabe: Finden Sie Klassen bzw. Objekte zu folgenden Begriffen: Leo, Tiger, Samurai, Elefant, Taigon, Benjamin Blümchen, Tier, Löwe
Lösung: Beim Programmieren muss man aus einer Aufgabenstellung immer wieder Objekte und Klassen identfizieren, die man zur Implementierung benötigt. Man kann z.B. alle Subjekte der Aufgabenstellung suchen und sich dazu fragen "ist das ein Objekt oder sind das viele Objekte?". In letzterem Fall hat man einen Kandidaten für eine Klasse. Sonst ist es ein Objekt. Nicht alle Objekte werden für das Programm benötigt.
Bei diesem Beispiel ist nur eine Liste von Tieren und Namen gegeben. Namen sind normalerweise Objekte, die verschiedenen Tiere sind natürlich Klassen.
Wir werden also die Klassen Tier, Tiger, Löwe und Elefant haben. Die anderen Begriffe sind konkrete Namen. Weiters können wir die "is-a" ("ist-ein") Beziehung Tiger is-a Tier, Löwe is-a Tier und Elefant is-a Tier ausmachen.
Damit ergibt sich folgendes Bild:
Kästchen mit unterstrichenen Namen stellen konkrete Objekte dar.
Die strichlierten Pfeile stellen die Instanzierung dar. Sie sind in Pfeilrichtung zu lesen: Leo ist-ein-konkreter Löwe (Leo is-instance-of Löwe) oder Samurai ist-ein-konkreter Tiger.
Die Pfeile mit Dreiecksspitzen und durchgehenden Linien stehen für die Vererbung (is-a, ist-ein), Beispielsweise Löwe ist-ein Tier (Löwe is-a Tier).
In Python könnte man das Beispiel so implementieren:
class Tier: def __init__(self): self.name = "" def setName(self, name): self.name = name def __str__(self): # toString() in Java return self.name class Loewe(Tier): pass class Elefant(Tier): pass class Tiger(Tier): pass leo = Loewe() leo.setName("Leo") benjamin = Elefant() benjamin.setName("Benjamin Blümchen") samurai = Tiger() samurai.setName("Samurai") taigon = Tiger() taigon.setName("Taigon"); print(leo) print(benjamin) print(samurai) print(taigon)
Erstellen Sie für die folgenden Beispiele passende Klassen- bzw. Objektdiagramme (UML) und implementieren Sie die in Python!
Beispiel 1
Mensch, Lebewesen, Mohrle, Mann, Paul, Paula, Helmut, Rex, Frau, Tier, Susi, Biene Maya, Pinocchio
Beispiel 2
Verkehrsmittel, Schiff, Auto, Porsche von Herrn Mayer, Dreirad, Fahrrad, Dreirad von Maxi, Sportwagen, Käfer von Paula, Düsenjet von Daniel
Montag, 11. November 2013
Python class (POS1: 2BHIF)
Erzeugen Sie eine einfache Klasse für Sportler. Sportler haben in unserem Beispiel einen Namen, ein Geburtsdatum und eine Liste von Zeiten (z.B. wie schnell ist der die letzten 100m-Läufe gelaufen).
Nennen Sie die Klasse Sportler
class Sportler: pass
Definieren Sie eine Methode zur Ermittlung der besten (Lauf-)Zeit (minimale Zeit aus der Liste von Zeiten).
Legen Sie mindestens 3 Sportler an und lassen Sie deren Namen, das Geburtsdatum und Bestzeit ausgeben.
Labels: Aufgabe, POS1-2, Python
Montag, 4. November 2013
Python Objekte, Wiederholung Aufrufstack (POS1: 2BHIF)
Objekte
In Python sind alle Elemente Objekte. Folgendes Beispiel enthält ein paar solche Objekte:def fun(x): # auch ein Objekt! y = x * x return y f2 = fun # f1 ist eine Refernz auf fun lst = [1, 2, fun] # Liste mit 3 Objekten l2 = lst # l2 ist eine Refernz auf obige Liste erg = fun(2) print(erg) erg = f2(3) print(erg) print(f2 == fun) print(l2 == lst) print(lst)
Folgendes Bild zeigt den Speicher, wenn das Progarmm in der Zeile 3 angelangt ist, nach dem
f2(3)
(ist ja fun(3)
) in der Zeile 12 Aufgerufen wurde.
Sie können den Ablauf unter folgendem Link testen: objects.py
Sie sehen auf der rechten Seite die Objekte, welche Python angelegt hat. Der linke Bereich ("Frames") zeigt den Speicher, den Python für die (globalen) Variablen anlegt sowie den Speicher für die aufgerufene Funktion. Für jede Funktion wird so ein Bereich (Frame) angelegt und beim beenden wieder zerstört.
Pfeile stellen Referenzen dar. Zum Beispiel stellt der Pfeil von
lst
zum Listenobjekt [1, 2, fun]
dar. Auch l2
ist eine Referenz zu dieser Liste.
In dieser Liste gibt es eine weitere Referenz zur Funktion
fun
. Funktionsnamen sind also Referenzen zu "Funktions-Objekten" (die den Code der Funktion "enthalten").
Aufrufstack
Beim folgenden Beispiel können Sie sehen, wie Frames sich bei den Aufrufen der Funktionfact()
stapeln und dann in Folge wieder zerstört werden:
def fact(n): if n > 1: return n * fact(n - 1) else: return 1 f = fact(5) print(f)
Folgendes Bild zeigt die Frames, wenn das Programm die Zeile 5 erreicht (aber nicht ausgeführt) hat. Sie sehen einen Stapel von Frames. Ein Frame pro Aufruf. Diese Frames werden anschließend bei jedem
return
wieder zerstört. Man nennt diesen Stapel Aufrufstack:
Sie können den Ablauf unter folgendem Link testen: fact.py
Klassen
Bei Klassen handelt es sich um benutzerdefinierte Typen. D.h. es werden Typen angelegt, für die benutzerdefinierte Methoden (also objektgebundene Funktionen) definiert werden können:class Car: def __init__(self, cartype, kind, serNr): self.cartype = cartype # die Attribute type, self.kind = kind # kind und self.serNr = serNr # serNr sind in der Instanz def maxSpeed(self): if self.kind == "pickup": # Wenn Pickup, dann langsamer return 100.0 else: return 130.0 passat1 = Car("VW/Passat", "regular_car", 11142) jetta1 = Car("VW/Jetta", "small_car", 11143) ram1 = Car("Dodge/Ram", "pickup", 22242) fleet = [passat1, jetta1, ram1] # Fuhrpark for car in fleet: print(car.cartype, car.maxSpeed(), "km/h")
Mittels der Anweisung
class
wird ein neuer Typ definiert. Dieser heißt in diesem Fall ‘Car’. Wir sehen, dass es sich bei der class
Anweisung ebenfalls um eine Block - Anweisung handelt, da nach der Bezeichnung der Klasse (Car) der Doppelpunkt folgt und die danach folgenden Methoden eingerückt sind.
Die einzelnen Methoden werden wie Funktionen definiert. D.h. die Definition erfolgt durch das Schlüsselwort
def
. Als Unterschied gibt wird jedoch ein zusätzlicher Parameter an erster Stelle angeführt, der zur Ausführungszeit der Methode mit der Referenz des aktuellen Objektes vom Laufzeitsystem belegt wird.
Das folgende Bild zeigt, wie Python den Speicher für die Objekte und die Klasse angelegt hat.
Sie können das Programm hier ausführen car.py.
Die Ausgabe wäre wie folgt:
VW/Passat 130.0 km/h VW/Jetta 130.0 km/h Dodge/Ram 100.0 km/h
Durch Aufrufen der Klasse (durch Angabe des Klassennamens) und Übergabe der Initialisierungsparameter wird eine neue Instanz angelegt. Die übergebenen Parameter werden verwendet, um die spezielle Methdode
__init__
nach dem Anlegen der Instanz aufzurufen. D.h. zuerst wird das neue Objekt angelegt und danach wird diese spezielle Methode aufgerufen. Dazu wird auch dieser Methode die Referenz auf das gerade angelegte Objekt mitgegeben (als Parameter self
).
D.h. in der Methode
__init__
werden die Attribute cartype
, kind
und serNr
für das gerade erzeugte Objekt angelegt. D.h. ab diesem Zeitpunkt besitzt das Objekt diese Attribute. Die Methode maxSpeed
kann danach ebenfalls auf diese Attribute zugreifen.
Attribute gehören also zu einem Objekt und können in den Methoden abgefragt und verändert werden. Anders als in anderen Programmiersprachen ist es jedoch so, dass der Zugriff auf diese Attribute nicht nur ausschließlich in den Methoden erfolgen kann. Diese Attribute können prinzipiell auch von außerhalb gelesen und verändert werden, wie man in obigem Beispiel in der Zeile 21 (
print(...)
) sehen kann.
Übungen (POS1: 2BHIF)
Theorie
- Was ist eine Variable?
- Welche Grunddatentypen kennen Sie?
- Was ist ein Liste?
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente einer Liste zu ermitteln, die ein bestimmtes Kriterium (z.B. ist größer als ein bestimmter Wert) erfüllen.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente eine Liste von Listen zu ermitteln, die ein bestimmtes Kriterium erfüllen.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte einer Liste zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte einer Liste zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte einer Liste von Listen zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte einer Liste von Listen zu ermitteln.
- Was ist eine Funktion? Geben Sie ein Beispiel in Python inklusive der Verwendung der Funktion.
- Wozu benötigt man Kommentare?
- Wozu benötigt man Programmierrichtlinien?
- Was ist ein Dictionary in Python?
- Was bedeutet der Begriff "Sequenz" in Python? Geben Sie einige Beispiele.
- Was muss grundsätzlich (ohne Programmdetails) gemacht werden, um von einer Datei zu lesen?
- Was muss grundsätzlich (ohne Programmdetails) gemacht werden, um in eine Datei zu schreiben?
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Zeilen einer Textdatei zu ermitteln, die ein bestimmtes Kriterium (z.B. enthält einen bestimmten String) erfüllen.
- Welche Arten von Programm(ier)fehlern kennen Sie? Wie findet man diese Fehler?
- Was ist der Aufrufstack? Erklären Sie den Verwendungszweck und die Funktionsweise.
In diesem Blog gibt es bereits eine Reihe von Aufgaben. Vergleichen Sie Ihre Lösungen mit jenen Ihrer MitschülerInnen.
Hier noch ein paar "Grundübungen":
- Erstellen Sie ein Pythonprogramm, welches das Maximum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten
[-1, -23, -2, -32, -89, -100, -1, -99]
. Finden Sie weitere Beispieltestdaten. - Erstellen Sie ein Pythonprogramm, welches das Minimum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten
[1, 23, 2, 32, 89, 100, 1, 99]
. Finden Sie weitere Beispieltestdaten. - Erstellen Sie ein Pythonprogramm, welches die Häufigkeit von Elementen einer Sequenz (Liste) ermittelt. Definieren Sie dazu eine Testsequenz mit folgenden Werten
[1, 2, -3, 4, 2, 1, 10, -3, 4, 2, 2, 10]
bzw.["hallo", "du", "test", "du", "Maus", "test", "Test"]
. Das Ergebnis soll eine Liste von unterschiedlichen Werten sein und wie oft sie vorkommen. - Folgende Ausgabe soll erzeugt werden:
1 3 5 7 9
. Lösen Sie die Aufgabe- mithilfe einer
while
-Schleife - mithilfe einer
for
-Schleife und des Modulo-Operators - mithilfe einer
for
-Schleife ohne den Modulo-Operator
- mithilfe einer
- Folgende Ausgabe soll erzeugt werden:
1 2 4 7 11 16 22 29 37
. Lösen Sie die Aufgabe- mithilfe einer
while
-Schleife - mithilfe einer
for
-Schleife
- mithilfe einer
Labels: Aufgabe, POS1-2, Python
Abonnieren Posts [Atom]