Lehrzeit

Schule & Informatik

Programmieraufgabe 78

Eigentlich hätte ich gedacht, dass ich diese Aufgabe schon längst mal aufgenommen hatte, stimmte aber nicht. Dabei ist sie zu Beginn der Q11 super zum Glätten der Leistungsunterschiede bei den Schülern und um schon mal zu sehen, wer was kann und wie gut. Außerdem lässt sich prima die Warteschlange als einfach verkettete Liste motivieren, da die Aufgabe mit einem Array umgesetzt nicht sehr performant ist.

Aufgabe 78
Schreibe ein Programm zur Verwaltung der Taxiwarteschlange an einem beliebigen Bahnhof.
Benutze dabei ein Feld Taxi, wobei die Anzahl der Taxen vom jeweiligen Bahnhof abhängt.

Die Klasse Taxi muss mindestens das Attribut fahrerName besitzen.

Implementiere für die Klasse TaxiWarteschlange mindestens folgende Methoden:

1.) pop() entfernt das vorderste Taxi
2.) push(neuesTaxi) hängt ein Taxi hinten an.
3.) aufruecken() rückt alle Taxen um 1 nach vorne und wird nach der Ausführung von pop() benötigt.

Die Überleitung bzw. Motivierung zur einfach verketteten Liste geschieht dann durch folgendes Szenario: Ein Taxifahrer hat eventuell einen Dauerkunden, der immer zu einer bestimmten Uhrzeit abgeholt werden muss (z.B. eine Dialysepatient). Daher kann ein Taxi auch mal aus der Mitte der Warteschlange herausfahren. Daraufhin müssen entsprechend  alle Taxen aufrücken.

Die Lösung dieses Problems mag für einen erfahreren Programmierer einfach sein. Für viele Schüler ist es aber überhaupt nicht. Oft bekomme ich eine Lösung mit drei geschachtelten Schleifen, also O(n3), anstelle einer einfachen, linearen Lösung.

Während meine Schüler das im Moment mit Java umsetzen, versuche ich mich an Python. Was nicht ganz einfach ist, da die Syntax dann doch zunächst sehr anders ist. Hier ein kleiner Auszug vom Start:

class TaxiSchlange:
    def __init__(self):
        self.__schlange = []

    def push(self, neuesTaxi):
        self.__schlange.append(neuesTaxi)

    def p(self):
        for el in self.__schlange:
            el.p()

Als erstes gibt es kein private oder public, in Python geht das mit Unterstrichen. Es gibt statt Arrays, Tupel bzw. statt ArrayListen die Listen. Die habe ich oben bemüht. Wodurch aber manches anders wird. Auch das Attribute erst im Konstruktor, der hier __init__ heißt, definiert werden, fand ich ungewöhnlich. Aber mit der Zeit wird man sich wohl daran gewöhnen.

10 Kommentare

  1. Schön, dass immer mehr von Java zu Python wechseln. Viele versuchen leider die Konzepte von Java 1:1 auf Python zu übertragen, was zu unschönem (und langem) Quelltext führt. Python geht da ein paar Wege anders, deswegen ein paar Bemerkungen zu deinem Quelltext:

    __init__ ist nicht ein Konstruktor (im Sinne von etwas konstruieren) sondern eine Initialisierungsmethode (deswegen der Name). __init__ bekommt ja auch eine Instanz mittels dem Parameter self übergeben, d. h. das Objekt ist schon bereits erzeugt. Es gibt daher auch eine magic method __new__(), die das Objekt erzeugt. In __init__() werden dann ggf. Default-Werte gesetzt oder wie bei dir eben eine leere Liste erzeugt.

    Die Unterstriche würde ich persönlich weglassen, da es trotzdem möglich ist, auf die Liste von außen zuzugreifen, Stichwort name mangling:
    http://stackoverflow.com/questions/7456807/python-name-mangling-when-in-doubt-do-what
    Ich lese immer wieder Quelltext, wo z.B. für jedes Attribut eine getter- und setter-Methode geschrieben wird, was unter Python nicht notwendig ist. Ich empfehle mal folgende Lektüren:
    http://dirtsimple.org/2004/12/python-is-not-java.html
    http://blog.pohlers-web.de/python-die-bessere-programmiersprache-fuer-den-informatikunterricht/ (hab mir da vor 1,5 Jahren mal den Frust von der Seele geschrieben) 😉

    Was die Methode p() machen soll erschließt sich mir nicht ganz?
    Generell halte ich meine Schüler an, keine Abkürzungen in Bezeichnern zu verwenden, es sei denn es ist eindeutig, dass es sich z.B. um eine Zählvariable handelt o.ä.. In der Methode p() würde ich dann auch element ausschreiben und der Methode p einen vollständigen Namen geben, dann weiß man auch, was die machen soll 😉

    Generell entwerfe ich immer mit meinen Schülern eine eigene Klasse Queue und verwende dort absichtlich nicht die built-in Liste, denn das sieht immer wie künstlich aufgestülpt aus. Außerdem wird so die lineare Struktur (also jeder Knoten in der Liste kennt nur seinen Nachfolgeknoten) imho deutlicher. Wenn du Interesse hast, lasse ich sie dir gerne zukommen.

    Ansonsten viel Spaß mit Python, es lohnt sich wirklich und macht enorm viel Spaß!

    • Danke für die vielen tollen Hinweise und Links. Das hilft natürlich bei der Einarbeitung. Und das der Quelltext nicht perfekt ist, war mir klar, deswegen hatte ich ihn geschrieben und gehofft, dass jemand wie du sich meldet und ein paar produktive Bemerkungen macht. Ich werde das dann mal anpassen und zeigen.

      Noch inhaltlich: Die Methode p() lasse ich von den Schülern in allen Klassen definieren und steht für print(). Sie dient dem schnellen Ausgeben der Attribute etc. der entsprechenden Objekte. Da die Schüler zu Beginn der 11. Klasse teilweise noch keinen Debugger kennen und sich selbst später schwer tun, ist es manchmal einfacher nur die mal die Objekte auszugeben. Und da ist dann jedesmal „System.out.println(objektName)“ schon ziemlich lang im Vergleich zu objektName.p().

      Die Klasse Queue, die du ansprachst, werde ich auch gemäß des Lehrplans mit einem Kompositum-Entwurfsmuster als einfach verkettete Liste umsetzen. ArrayList würde ich nur benutzen, wenn ich z.B. Adjazenzlisten bei den Graphen benützen würde.

      • Dann wirst du dich direkt mal wieder über Python freuen, denn du kannst dir in Python direkt ohne Umwege das Objekt samt Speicherstelle ausgeben lassen:

        In [1]: class A: pass
        In [2]: a = A()
        In [3]: print a

        In [4]: b = A()

        Wenn es noch mehr Informationen sein soll, bietet jede Klasse die magic-methods __str__(), die dann überschrieben werden muss. Diese Methode muss einen String zurückgeben, der dann beim Aufruf mit print ausgegeben wird. Hier mal ein paar Beispiele mit Python3:

        In [5]: class A:
        …: def __str__(self):
        …: return „Ich bin ein Objekt“

        In [6]: a = A()
        In [7]: print(a)
        Ich bin ein Objekt

        Oder halt alternativ mit Werten der jeweiligen Instanz:

        In [8]: class A:
        ….: def __init__(self):
        ….: self.wert = 10
        ….: def __str__(self):
        ….: return „Mein Wert ist {}.“.format(self.wert)

        In [9]: a = A()
        In [10]: print(a)
        Mein Wert ist 10.
        In [11]: a.wert = 15
        In [12]: print(a)
        Mein Wert ist 15.

  2. Hi Ingo,
    schön, dass du zu Python wechselst!
    Als große Inspiration kann ich dir übrigens die iPython Notebooks von Peter Norvig empfehlen. Ganz aktuell z.B. das hier zu Wahrscheinlichkeitsparadoxien: http://nbviewer.ipython.org/url/norvig.com/ipython/Probability.ipynb

    Aber Achtung: Das ist fast nie objektorientiertes Python, sondern sehr funktional. (Viele higher-order functions usw.) Richtig „schöne“ Programme, finde ich. Ganz kurz und knackig, ganz nahe daran wie man über das Problem „denkt“, nicht wie man es mühsam einer Maschine vorbuchstabieren muss.
    Dazu in diesem Beispiel noch eine wichtige Lektion für’s Leben: das Reasonable Person Principle.

    Allgemein sind die iPython Notebooks ne tolle Sache. Wenn ich mal endlich auch Python unterrichten darf, werde ich die bestimmt im Unterricht einsetzen.

    • Danke für das „Willkommen“. Ob Python sich bei mir an der Schule durchsetzen wird, wird sich erst noch zeigen. Aber ich bin guten Mutes, obwohl ich jetzt schon damit kämpfe keine „normalen“ Arrays zur Verfügung zu haben und bestimmte Probleme zu zeigen. Aber da fehlt mir noch der Durchblick und die letzte Nacht habe ich ausnahmsweise mal gut geschlafen.
      Was mich aber von Anfang an gestört hat, ist das Tcl/Tk. Das habe ich ja schon vor 20 Jahren an der Uni benutzt, um Oberflächen bei C++ zu programmieren. Kann mir jemand da mal einen Tipp geben, wie man am einfachsten an GUIs kommt? Auch ein Drag&Drop-Programm für Oberflächen wäre schön, so wie beim Java-Editor oä.

  3. Ich verwende Qt, bzw. die Python-Anbindung dafür heißt PyQt/PySide. Da ist auch der Qt-Designer dabei, mit dem man nur die Oberfläche erstellt und diese dann zur Laufzeit in sein Programm einbindet.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

*

© 2017 Lehrzeit

Theme von Anders NorénHoch ↑