Montag, 25. November 2013

 

Java Forever And Ever Movie (JAVA vs Windows .Net)

Labels: ,


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 ferig
oder 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: , , ,


 

Römische Zahlen umwandeln (POS1: 2BHIF)

Abgabename: 2013_2bhif_aufgabe6_name_vorname.tgz

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 ... 1000
Beachten 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 zahl
einliest, 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 > 
Zum Schluss wurde EOF eingegeben (Strg-D), die Eingaben sind fett gedruckt.

Informationen finden Sie unter:

Labels: , , ,


Mittwoch, 13. November 2013

 

Einführung Objektorientiertes Programmieren (POS1: 2BHIF)

Sie finden hier ein paar Informationen zum objektorientierten Programmieren und den von uns verwendeten Begriffen:
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

Labels: ,


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: , ,


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 Funktion fact() 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.

Labels: ,


 

Übungen (POS1: 2BHIF)

Sie finden an dieser Stelle eine Reihe von Fragen und Aufgaben, die Sie jetzt beantworten bzw. lösen können sollten. Aussagenlogik ist bei diesen Fragen ausgeklammert.

Theorie
  1. Was ist eine Variable?
  2. Welche Grunddatentypen kennen Sie?
  3. Was ist ein Liste?
  4. 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.
  5. Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente eine Liste von Listen zu ermitteln, die ein bestimmtes Kriterium erfüllen.
  6. Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte einer Liste zu ermitteln.
  7. Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte einer Liste zu ermitteln.
  8. Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte einer Liste von Listen zu ermitteln.
  9. Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte einer Liste von Listen zu ermitteln.
  10. Was ist eine Funktion? Geben Sie ein Beispiel in Python inklusive der Verwendung der Funktion.
  11. Wozu benötigt man Kommentare?
  12. Wozu benötigt man Programmierrichtlinien?
  13. Was ist ein Dictionary in Python?
  14. Was bedeutet der Begriff "Sequenz" in Python? Geben Sie einige Beispiele.
  15. Was muss grundsätzlich (ohne Programmdetails) gemacht werden, um von einer Datei zu lesen?
  16. Was muss grundsätzlich (ohne Programmdetails) gemacht werden, um in eine Datei zu schreiben?
  17. 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.
  18. Welche Arten von Programm(ier)fehlern kennen Sie? Wie findet man diese Fehler?
  19. Was ist der Aufrufstack? Erklären Sie den Verwendungszweck und die Funktionsweise.
Praxis:
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":
  1. 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.
  2. 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.
  3. 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.
  4. 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

  5. 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

Labels: , ,


This page is powered by Blogger. Isn't yours?

Abonnieren Posts [Atom]