Übungsaufgaben zu objektorientierten Algorithmen: Methoden über Objektlisten
https://bildung.social/@oerinformatik/
https://oer-informatik.de/algorithmen-objektorientiert-uebungsaufgaben
Objektorientierte Algorithmen, Pseudocode, Objektlisten, Lineare Suche, Schreibtischtest, Polymorphie, UML-Klassendiagramm, Übungsaufgaben, Prüfungsvorbereitung
tl/dr; (Bearbeitungszeit insgesamt 130 min, mehrere Aufgaben): Fünf Übungsaufgaben, in denen Du Methoden über Listen und Arrays von Objekten in Pseudocode schreibst: einen Monatsbericht mit Kennzahlen und fehlenden Werten erstellen, Barcamp-Anmeldungen aus einer CSV-Datei importieren und Dubletten erkennen, Mitfahrangebote filtern, sortieren und anfragen, Absatz und Wochentagsumsatz mit Map und Array auswerten, einen fehlerhaften Entwurf per Schreibtischtest prüfen, eine Haltephase im Ofenprotokoll finden sowie eine seitenweise Schnittstelle, polymorphe Statusmeldungen, eine Rundenplanung und eine Raumbelegung für ein Barcamp bearbeiten. Alle Lösungen sind ausgeblendet, in vier Pseudocode-Notationen umschaltbar und mit Punkteverteilung versehen [AI-Assisted]. (Zuletzt geändert am 28.10.2026)
Diese Übungsaufgaben gehören zum Artikel Objektorientierte Algorithmen: Methoden über Objektlisten. Sie setzen voraus, dass Du Algorithmen in Pseudocode notieren und UML-Klassendiagramme lesen kannst.
Hinweise zur Bearbeitung: Als FIA oder FIDP musst Du zur Teil-2-Prüfung Aufgaben auf Kernkompetenz-Ebene lösen können, das sind Aufgabe 2.1 und Aufgabe 2.2. Von FIA wird zusätzlich erwartet, dass ihnen Aufgaben auf Profilkompetenz-Ebene (Aufgabe 3.1, Aufgabe 3.2 und Aufgabe 3.3) keine Probleme bereiten. Schreibe Deine Lösung zuerst auf Papier, bevor Du die Beispiellösung aufklappst.
Du kannst in einer der vier Pseudocode-Notationen antworten; die Beispiellösungen stehen in allen vier zur Auswahl. Die Notationen sind im Artikel Algorithmen mit Pseudocode dokumentieren beschrieben. So sieht eine Schleife über eine Liste von Objekten aus:
für jedes a in aktivitaeten
summe := summe + a.getZusagen()
Ende für
Für Listen gibt es in JANA und beiden Pascal-Varianten die Methoden add(t) (anhängen), add(i, t) (an Position i einfügen), size() und get(i) (erste Position: 0); in Pseudo-Python sind es append(t), insert(i, t), len(liste) und liste[i]. Ein Struktogramm oder eine echte Programmiersprache ist ebenfalls richtig. Auf private Attribute greifst Du nur über Getter und Setter zu. Andere fachlich richtige Lösungen bekommen die volle Punktzahl.
Du möchtest eigene Aufgaben zum Üben von einem KI-Sprachmodell generieren lassen?
Kopiere den Text in ein KI-Sprachmodell Deiner Wahl und passe Kompetenzstufe, Anzahl, Bearbeitungszeit und Szenario bei Bedarf an. Wie die Aufgaben aufgebaut sind, beschreibt der Artikel Wie sind die Aufgaben aufgebaut?. Prüfe die Ergebnisse mit dem Lehrartikel: KI-Sprachmodelle machen Fehler.
Erstelle neue Übungsaufgaben zum Thema „Objektorientierte Algorithmen:
Methoden über Objektlisten“.
Bauplan: Halte Dich an Aufbau, Kompetenzstufen, Operatoren,
Anforderungsbereiche, Punkte und Zeitschätzung, die im Artikel
https://oer-informatik.de/aufgaben-aufbau beschrieben sind.
Fachliche Grundlage:
- https://oer-informatik.de/algorithmen-objektorientiert
- https://oer-informatik.de/pseudocode
- https://oer-informatik.de/uml-klassendiagramm
- https://oer-informatik.de/programmentwurfstechniken
- https://oer-informatik.de/uml-klassendiagramm-polymorphie
- Stilbeispiel: https://oer-informatik.de/algorithmen-objektorientiert-uebungsaufgaben
Die Aufgaben sollen Inhalte zu diesen Schlagwörtern abdecken:
- Objektorientierte Algorithmen
- Pseudocode
- Objektlisten
- Lineare Suche
- Schreibtischtest
- Polymorphie
- UML-Klassendiagramm
Kompetenzstufe: Profilkompetenz (alternativ: Basiskompetenz, Kernkompetenz, Expertise)
Anzahl: 1 Aufgabe mit Teilaufgaben
Bearbeitungszeit in Minuten ca.: <5 bis 30 min>
Szenario: eines der Szenarien aus dem Bauplan
Vorgehen:
1. Lies zuerst die verlinkten Artikel. Kannst Du keine Webseiten
abrufen, sag mir das, statt zu raten.
2. Steht bei einer Angabe noch ein Platzhalter in <…>, frag mich
zuerst danach. Richte Punkte und Zahl der Teilaufgaben nach der
Bearbeitungszeit (ca. 0,9 min je Punkt).
3. Gib je Aufgabe Titel mit Kompetenzstufe, Ausgangssituation und
Teilaufgaben mit Operator und Punktzahl aus, dazu die geschätzte
Bearbeitungszeit.
4. Gib die Beispiellösungen mit Punkteverteilung erst aus, wenn ich
danach frage.
Aufgabe 2.1: Aktivitäten eines Monats auswerten (Kernkompetenz)
(ca. 26 min Bearbeitungszeit)
In der App der Let’s Meet GmbH melden Organisator*innen nach jeder Aktivität, wie viele der Zugesagten tatsächlich gekommen sind. Geschäftsführerin Clara Neumann möchte jeden Monat einen kurzen Bericht über das Angebot sehen. Du entwickelst ihn mit Mit-Azubi Jonas Weber.
Die Aktivitäten eines Monats liegen in der Liste aktivitaeten vom Typ List<Aktivitaet>:
Aktivitaethat die Attributetitel: String,plaetze: Integer,zusagen: Integerunderschienen: Integer [0..1]mit öffentlichen Gettern.erschienenistnull, solange die Organisatorin oder der Organisator nichts gemeldet hat.Die Klasse
Monatsberichthat den KonstruktorMonatsbericht(ausgebucht: Integer, noShowQuote: Real, schwaechste: Aktivitaet, ohneMeldung: Integer).
Der Bericht enthält:
ausgebucht: die Zahl der Aktivitäten, bei denen die Zusagen die Plätze erreichen,
noShowQuote: den Anteil der Zusagen in Prozent, die nicht erschienen sind; berücksichtigt werden nur Aktivitäten mit Meldung, und es wird über alle diese Zusagen zusammen gerechnet,
schwaechste: die gemeldete Aktivität mit der kleinsten Auslastung (Erschienene geteilt durch Plätze); bei Gleichstand die zuerst gefundene, ohne gemeldete Aktivität
null,ohneMeldung: die Zahl der Aktivitäten ohne Meldung.
Aktivitäten im September 2026 (Auszug):
| titel | plaetze | zusagen | erschienen |
|---|---|---|---|
| Boule im Bürgerpark | 8 | 8 | 7 |
| Thai-Kochabend | 6 | 6 | 6 |
| Lauftreff am Obersee | 12 | 9 | null |
| Brettspielabend | 10 | 7 | 4 |
| Radtour im Teuto | 15 | 15 | 11 |
| Fotowalk Altstadt | 10 | 4 | 3 |
| Führung Sparrenburg | 20 | 11 | null |
a) Lege vor dem Programmieren die erwarteten Ergebnisse fest: Bestimme die vier Werte des Berichts für die Beispieldaten von Hand und gib für die noShowQuote den Rechenweg an. (5 Punkte)
ausgebucht = 3: Boule, Thai-Kochabend und Radtour (Zusagen = Plätze).
ohneMeldung = 2: Lauftreff und Führung.
noShowQuote = 22,5 %: Gemeldet sind fünf Aktivitäten mit 8 + 6 + 7 + 15 + 4 = 40 Zusagen und 7 + 6 + 4 + 11 + 3 = 31 Erschienenen. Nicht erschienen sind 9; \frac{9}{40} \cdot 100 = 22{,}5\ \%.
schwaechste = Fotowalk Altstadt: Auslastungen 0,875; 1,0; 0,4; 0,733; 0,3.
Je Wert 1 Punkt, Rechenweg der Quote 1 Punkt.
b) Entwickle die Methode erstelleBericht(aktivitaeten: List<Aktivitaet>): Monatsbericht. Sie soll mit einem einzigen Durchlauf durch die Liste auskommen und darf bei einer leeren Liste oder ohne gemeldete Aktivität nicht abbrechen. (16 Punkte)
Funktion erstelleBericht(aktivitaeten: List<Aktivitaet>): Monatsbericht
ausgebucht: integer := 0
ohneMeldung: integer := 0
summeZusagen: integer := 0
summeErschienen: integer := 0
schwaechste: Aktivitaet := null
minAuslastung: double := 0.0
für jedes a in aktivitaeten
wenn a.getZusagen() >= a.getPlaetze() dann
ausgebucht := ausgebucht + 1
Ende wenn
wenn a.getErschienen() = null dann
ohneMeldung := ohneMeldung + 1
sonst
summeZusagen := summeZusagen + a.getZusagen()
summeErschienen := summeErschienen + a.getErschienen()
auslastung: double := a.getErschienen() * 1.0 / a.getPlaetze()
wenn schwaechste = null oder auslastung < minAuslastung dann
schwaechste := a
minAuslastung := auslastung
Ende wenn
Ende wenn
Ende für
quote: double := 0.0
wenn summeZusagen > 0 dann
quote := (summeZusagen - summeErschienen) * 100.0 / summeZusagen
Ende wenn
Rückgabe new Monatsbericht(ausgebucht, quote, schwaechste, ohneMeldung)
Ende erstelleBericht
Die Auslastung wird mit * 1.0 zur Kommazahl, sonst ergäbe die Division zweier Ganzzahlen in vielen Sprachen 0. Für die Beispieldaten liefert die Methode die Werte aus a).
Bewertung:
| Baustein | Punkte |
|---|---|
| Zähler, Summen und Merker vor der Schleife angelegt | 2 |
| eine Schleife über alle Aktivitäten | 1 |
ausgebuchte Aktivitäten mit >= gezählt |
2 |
fehlende Meldung über null erkannt und gezählt, bevor getErschienen() weiterverwendet wird |
3 |
| Summen nur über gemeldete Aktivitäten | 2 |
| schwächste Aktivität: Auslastung als Kommazahl, erster Wert berücksichtigt, Objekt gemerkt | 3 |
| Quote in Prozent, Division durch 0 abgefangen | 2 |
| Rückgabe über den Konstruktor | 1 |
Ein Struktogramm mit denselben Bausteinen erhält die volle Punktzahl.
c) Jonas möchte die No-Show-Quote anders berechnen: erst für jede gemeldete Aktivität die Quote, dann den Durchschnitt dieser Quoten. Berechne seinen Wert für die Beispieldaten und vergleiche ihn mit dem Wert aus a). Welche Berechnung passt besser zu Claras Frage, wie viele zugesagte Plätze leer geblieben sind? (4 Punkte)
Quoten je Aktivität: Boule 12,5 %, Thai-Kochabend 0 %, Brettspielabend 42,86 %, Radtour 26,67 %, Fotowalk 25 %. Durchschnitt: \frac{12{,}5 + 0 + 42{,}86 + 26{,}67 + 25}{5} \approx 21{,}4\ \% (2 Punkte).
Die Berechnung über alle Zusagen (22,5 %) beantwortet Claras Frage direkt: Sie zählt jede leere Zusage gleich, große Aktivitäten zählen also mehr. Jonas’ Durchschnitt gewichtet jede Aktivität gleich; eine kleine Aktivität mit vier Zusagen beeinflusst ihn genauso stark wie die Radtour mit fünfzehn (2 Punkte). Sein Wert ist sinnvoll, wenn gefragt ist, wie zuverlässig eine typische Aktivität besucht wird.
d) Clara schlägt vor: „Die schwächste Aktivität nehmen wir im nächsten Monat aus dem Programm.“ Beurteile, ob der Bericht diese Entscheidung trägt, und schlage eine bessere Grundlage vor. (3 Punkte)
Die Auslastung mischt zwei Ursachen: Der Fotowalk hatte wenige Zusagen (geringes Interesse oder schlechte Sichtbarkeit in der App), aber drei von vier Zugesagten sind gekommen – die Zuverlässigkeit ist gut (1 Punkt). Ein einzelner Monat mit einem Termin ist außerdem eine sehr kleine Grundlage (1 Punkt). Besser: Zusagequote (Zusagen je Platz) und Erscheinensquote getrennt betrachten, über mehrere Monate vergleichen und die Organisator*innen nach Gründen fragen, etwa Termin oder Wetter (1 Punkt).
Aufgabe 2.2: Anmeldungen für das Barcamp importieren (Kernkompetenz)
(ca. 24 min Bearbeitungszeit)
Für das Barcamp „Lernen.Digital.Leben 2027“ am Ratz und Rübe Berufskolleg melden sich Teilnehmende, Referent*innen und Ausstellende über ein Online-Formular an. Das Formular liefert eine CSV-Datei, die regelmäßig in die Orga-Software übernommen wird. Dimitrios Papadopoulos aus der Orga-Leitung bittet Dich, die Importmethode zu schreiben.
Vorhanden sind:
Anmeldungmit den Attributenemail,nameundrolle(alleString), Gettern, Settern und dem KonstruktorAnmeldung(email: String, name: String, rolle: String).Teilnehmerverwaltungmit den Attributenanmeldungen: List<Anmeldung>undprotokoll: List<String>, der Methodesuche(email: String): Anmeldung(liefert die Anmeldung mit dieser E-Mail-Adresse odernull) und der zu schreibenden Methodeimportieren(pfad: String): Integer.Textdatei.liesAlleZeilen(pfad: String): List<String>(statisch) liefert alle Zeilen der Datei; die erste Zeile ist die Kopfzeileemail;name;rolle.Zeichenketten bieten
split(trenner): String[],trim(): String(Leerzeichen am Rand entfernen),toLowerCase(): Stringundcontains(teil): Boolean. In Pseudo-Python heißen siesplit,strip,lowerundteil in text.splitliefert auch leere Felder, z. B. am Zeilenende.
Für den Import gilt:
Eine Zeile muss genau drei Felder haben, sonst wird sie nicht übernommen und im Protokoll als „Zeile N: Feldzahl“ vermerkt (N ist die Zeilennummer in der Datei, die Kopfzeile ist Zeile 1).
Die E-Mail-Adresse wird ohne Leerzeichen am Rand und in Kleinbuchstaben gespeichert. Enthält sie kein
@, wird die Zeile nicht übernommen: „Zeile N: E-Mail ungültig“.Eine leere Rolle wird zu „Teilnahme“.
Gibt es zur E-Mail-Adresse schon eine Anmeldung, entsteht keine neue; Name und Rolle der vorhandenen werden durch die Werte der Zeile ersetzt: „Zeile N: aktualisiert“.
importieren gibt die Zahl der neu angelegten Anmeldungen zurück.
a) In der Teilnehmerverwaltung steht bereits die Anmeldung von mia.schroeder@rrbk.example. Entscheide für jede Datenzeile der folgenden Datei, was der Import damit macht, und gib den Rückgabewert an. (6 Punkte)
email;name;rolle
mia.schroeder@rrbk.example;Mia Schröder;Referentin
Hannah.Klein@RRBK.example ;Hannah Klein;
marco.brenner(at)webwerk.example;Marco Brenner;Teilnahme
fatma.oeztuerk@rrbk.example;Fatma Öztürk
hannah.klein@rrbk.example;Hannah Klein;Helferin
jan.peters@peters-elektro.example;Jan Peters;Aussteller
| Zeile | Ergebnis | Begründung |
|---|---|---|
| 2 | aktualisiert, Rolle jetzt „Referentin“ | Mias Adresse ist schon vorhanden (Regel 4) |
| 3 | neu: hannah.klein@rrbk.example, Rolle „Teilnahme“ |
Leerzeichen und Großbuchstaben bereinigt, leere Rolle ersetzt (Regeln 2 und 3) |
| 4 | nicht übernommen, „E-Mail ungültig“ | kein @ (Regel 2) |
| 5 | nicht übernommen, „Feldzahl“ | nur zwei Felder (Regel 1) |
| 6 | aktualisiert, Rolle jetzt „Helferin“ | die Adresse wurde in Zeile 3 angelegt (Regel 4) |
| 7 | neu: Jan Peters, Rolle „Aussteller“ | – |
Rückgabewert: 2. Je Zeile 1 Punkt (Ergebnis mit Begründung).
b) Programmiere die Methode importieren(pfad: String): Integer. (14 Punkte)
Funktion importieren(pfad: string): integer
zeilen: List<string> := Textdatei.liesAlleZeilen(pfad)
neu: integer := 0
zähle i von 1 bis zeilen.size() - 1
felder: string[] := zeilen.get(i).split(";")
wenn laenge(felder) <> 3 dann
protokoll.add("Zeile " & (i + 1) & ": Feldzahl")
sonst
email: string := felder[0].trim().toLowerCase()
rolle: string := felder[2].trim()
wenn rolle = "" dann
rolle := "Teilnahme"
Ende wenn
wenn nicht email.contains("@") dann
protokoll.add("Zeile " & (i + 1) & ": E-Mail ungültig")
sonst
vorhanden: Anmeldung := suche(email)
wenn vorhanden = null dann
anmeldungen.add(new Anmeldung(email, felder[1].trim(), rolle))
neu := neu + 1
sonst
vorhanden.setName(felder[1].trim())
vorhanden.setRolle(rolle)
protokoll.add("Zeile " & (i + 1) & ": aktualisiert")
Ende wenn
Ende wenn
Ende wenn
Ende zähle
Rückgabe neu
Ende importieren
Bewertung:
| Baustein | Punkte |
|---|---|
| Zeilen holen, Zählschleife ab Index 1 (Kopfzeile ausgelassen) | 2 |
Zeile mit split(";") zerlegt |
1 |
| Feldzahl geprüft und protokolliert, bevor auf die Felder zugegriffen wird | 2 |
E-Mail bereinigt (trim, toLowerCase) |
2 |
| leere Rolle ersetzt | 1 |
E-Mail mit contains("@") geprüft und protokolliert |
2 |
Dublette über suche erkannt, Werte per Setter ersetzt, protokolliert |
2 |
| neue Anmeldung mit Konstruktor angelegt und gezählt | 1 |
| Rückgabe der neuen Anmeldungen | 1 |
Die Zeilennummer im Protokoll ist i + 1, weil der Index bei 0 beginnt und die Kopfzeile Zeile 1 ist.
c) Regel 4 lässt eine spätere Zeile eine vorhandene Anmeldung überschreiben. Beurteile diese Regel aus Sicht der Datenqualität und nenne eine Verbesserung. (3 Punkte)
Vorteil: Es entstehen keine Dubletten (Eindeutigkeit), und Korrekturen wie Hannahs neue Rolle kommen an (Aktualität) (1 Punkt). Nachteil: Wer eine fremde oder vertippte E-Mail-Adresse einträgt, überschreibt ohne Rückfrage die Daten einer anderen Person; ob die neue Angabe stimmt, prüft niemand (Korrektheit) (1 Punkt). Verbesserung, z. B.: Änderungen erst nach Bestätigung über einen Link an die vorhandene Adresse übernehmen oder die Zeile nur protokollieren und von der Orga freigeben lassen (1 Punkt).
d) Die Prüfung mit contains("@") lässt noch viele unbrauchbare Adressen durch. Nenne zwei solche Beispiele und formuliere eine strengere Prüfregel in Worten. (3 Punkte)
Beispiele (1 Punkt): @rrbk.example, hannah@, hannah@@rrbk.example, hannah klein@rrbk.example.
Strengere Regel (2 Punkte), z. B.: Die Adresse enthält genau ein @, davor steht mindestens ein Zeichen, dahinter ein Domainname mit mindestens einem Punkt, der nicht am Anfang oder Ende steht, und sie enthält keine Leerzeichen. Ob es das Postfach wirklich gibt, zeigt erst eine Bestätigungs-E-Mail.
Aufgabe 3.1: Mitfahrangebote vermitteln (Profilkompetenz)
(ca. 24 min Bearbeitungszeit)
Du arbeitest als Auszubildende*r im FIA-Projektteam der Mitfahr-App RatzFahrt am Ratz und Rübe Berufskolleg in Bielefeld. Oksana Melnyk hat die Fachlogik objektorientiert entworfen. Deine Aufgabe ist es, die Vermittlung zwischen Gesuchen und Angeboten zu programmieren. Folgende Klassen sind vorhanden:
Für alle Attribute gibt es öffentliche Getter und Setter (z. B.
getFreiePlaetze(),getBuchungen()).HaltepunktundNutzervergleichen zwei Objekte mitequals(…)inhaltlich; Werte der AufzählungRichtungvergleichst Du direkt.z1.istVor(z2)lieferttrue, wennz1echt vorz2liegt;z1.gleicherTag(z2)lieferttrue, wenn beide Zeitpunkte auf denselben Kalendertag fallen.Zeitpunkt.jetzt()liefert den aktuellen Zeitpunkt.
Beispieldaten für Dienstag, den 20.10.2026 (Auszug aus der Liste angebote):
| Nr. | Fahrer*in | Haltepunkt | Richtung | Abfahrt | freie Plätze |
|---|---|---|---|---|---|
| 1 | Ben Richter | Gütersloh Hbf | ZUR_SCHULE |
20.10.2026 07:00 | 2 |
| 2 | Ben Richter | Gütersloh Hbf | NACH_HAUSE |
20.10.2026 14:20 | 3 |
| 3 | Thomas Becker | Gütersloh Hbf | ZUR_SCHULE |
20.10.2026 07:15 | 1 |
| 4 | Marie Schulz | Herford P&R | ZUR_SCHULE |
20.10.2026 06:50 | 3 |
| 5 | Ben Richter | Gütersloh Hbf | ZUR_SCHULE |
21.10.2026 07:00 | 2 |
| 6 | Jonas Wolff | Gütersloh Hbf | ZUR_SCHULE |
20.10.2026 07:25 | 0 |
| 7 | Emma Lorenz | Gütersloh Hbf | ZUR_SCHULE |
20.10.2026 06:55 | 3 |
Lukas Hofmann sucht eine Fahrt ab Gütersloh Hbf, Richtung ZUR_SCHULE, Abfahrt zwischen 20.10.2026 06:45 und 07:30 (beide Grenzen eingeschlossen). Für die Rückfahrt am 20.10. hat er bereits Angebot 2 angefragt.
a) Implementiere in der Klasse Fahrtenboerse die Methode passendeAngebote(g: Gesuch): List<Angebot>. Ein Angebot passt zum Gesuch g, wenn Haltepunkt und Richtung übereinstimmen, die Abfahrt im Zeitfenster liegt, mindestens ein Platz frei ist und die suchende Person nicht selbst fährt. Welche Angebote liefert die Methode für Lukas? (8 Punkte)
Funktion passendeAngebote(g: Gesuch): List<Angebot>
ergebnis: List<Angebot> := new List<Angebot>()
für jedes a in angebote
imFenster: boolean := nicht a.getAbfahrt().istVor(g.getFruehestens()) und nicht g.getSpaetestens().istVor(a.getAbfahrt())
gleicherWeg: boolean := a.getHaltepunkt().equals(g.getHaltepunkt()) und a.getRichtung() = g.getRichtung()
wenn gleicherWeg und imFenster und a.getFreiePlaetze() > 0 und nicht a.getFahrer().equals(g.getErsteller()) dann
ergebnis.add(a)
Ende wenn
Ende für
Rückgabe ergebnis
Ende passendeAngebote
„Im Fenster“ heißt: nicht vor dem frühesten und nicht nach dem spätesten Zeitpunkt. Weil istVor echt vergleicht, gehören beide Grenzen dazu. Für Lukas liefert die Methode die Angebote 1, 3 und 7 (in dieser Reihenfolge). Angebot 2 hat die falsche Richtung, 4 einen anderen Haltepunkt, 5 einen anderen Tag, 6 keinen freien Platz.
Bewertung: Ergebnisliste anlegen und zurückgeben 1 Punkt, Schleife 1 Punkt, Haltepunkt mit equals 1 Punkt, Richtung 1 Punkt, Zeitfenster mit istVor einschließlich der Grenzen 2 Punkte, freie Plätze 1 Punkt, eigene Angebote ausschließen und Ergebnis der Beispieldaten 1 Punkt.
b) Die App soll die passenden Angebote nach Abfahrt geordnet anzeigen, die früheste zuerst. Entwickle die Methode nachAbfahrtSortiert(g: Gesuch): List<Angebot>. Sie nutzt a) und fügt jedes Angebot an der richtigen Stelle in eine neue Liste ein. Bei gleicher Abfahrt bleibt die Reihenfolge aus a) erhalten. Gib das Ergebnis für Lukas an. (6 Punkte)
Funktion nachAbfahrtSortiert(g: Gesuch): List<Angebot>
sortiert: List<Angebot> := new List<Angebot>()
für jedes a in passendeAngebote(g)
pos: integer := 0
solange pos < sortiert.size() und nicht a.getAbfahrt().istVor(sortiert.get(pos).getAbfahrt())
pos := pos + 1
Ende solange
sortiert.add(pos, a)
Ende für
Rückgabe sortiert
Ende nachAbfahrtSortiert
Ergebnis für Lukas: 7 (06:55), 1 (07:00), 3 (07:15).
Die innere Schleife sucht die erste Position, deren Abfahrt später liegt als die des neuen Angebots. Weil bei Gleichstand weitergesucht wird, landet ein gleich frühes Angebot hinter dem vorhandenen; die Reihenfolge aus a) bleibt also erhalten (stabiles Sortieren durch Einfügen).
Bewertung: Methode aus a) nutzen 1 Punkt, neue Liste und Rückgabe 1 Punkt, Einfügeposition mit Abbruch am Listenende suchen 2 Punkte, Vergleich über istVor mit richtiger Behandlung gleicher Zeiten 1 Punkt, Einfügen mit add(pos, a) und Ergebnis 1 Punkt. Wer zuerst alles in eine Liste übernimmt und dann mit einem bekannten Sortierverfahren sortiert, erhält bei richtiger Umsetzung ebenfalls die volle Punktzahl.
c) Entwickle die Methode anfragen(a: Angebot, n: Nutzer): Boolean der Klasse Fahrtenboerse. Sie legt eine noch unbestätigte Buchung für n beim Angebot a an und liefert true. Sie liefert false und legt nichts an, wenn
kein Platz mehr frei ist oder
ndas Angebot selbst anbietet odernbereits eine Buchung bei irgendeinem Angebot derselben Richtung am selben Tag hat (auch beim Angebotaselbst).
Die Klasse Buchung erhält dafür den Konstruktor Buchung(mitfahrer: Nutzer, angefragtAm: Zeitpunkt), die Klasse Angebot die Methode buchungHinzufuegen(b: Buchung). Was liefern nacheinander anfragen(Angebot 1, Lukas), anfragen(Angebot 3, Lukas) und anfragen(Angebot 6, Lukas)? (8 Punkte)
Funktion anfragen(a: Angebot, n: Nutzer): boolean
wenn a.getFreiePlaetze() = 0 oder a.getFahrer().equals(n) dann
Rückgabe false
Ende wenn
konflikt: boolean := false
für jedes x in angebote
wenn x.getRichtung() = a.getRichtung() und x.getAbfahrt().gleicherTag(a.getAbfahrt()) dann
für jedes b in x.getBuchungen()
wenn b.getMitfahrer().equals(n) dann
konflikt := true
Ende wenn
Ende für
Ende wenn
Ende für
wenn konflikt dann
Rückgabe false
Ende wenn
a.buchungHinzufuegen(new Buchung(n, Zeitpunkt.jetzt()))
Rückgabe true
Ende anfragen
Ergebnisse: Angebot 1 → true (Lukas’ vorhandene Buchung gilt der Rückfahrt). Angebot 3 → false (inzwischen hat er bei Angebot 1 eine Fahrt zur Schule am selben Tag). Angebot 6 → false (kein Platz frei).
Bewertung:
Platz und eigenes Angebot vorab prüfen: 1 Punkt
Schleife über alle Angebote mit Bedingung gleiche Richtung und gleicher Tag: 2 Punkte
innere Schleife über die Buchungen des Angebots (über den Getter) mit
equals: 2 PunkteErgebnis der Suche in einer Variablen und erst nach den Schleifen ausgewertet: 1 Punkt
Buchung mit Konstruktor und
Zeitpunkt.jetzt()überbuchungHinzufuegeneingetragen: 1 Punkt (nicht direkt auf die private Liste zugreifen; die freien Plätze ändern sich erst bei der Bestätigung)Ergebnisse der drei Aufrufe: 1 Punkt
d) Ergänze das Klassendiagramm um alle Methoden und Konstruktoren, die Du in a) bis c) implementiert oder vorausgesetzt hast, und lege die Beziehungsart zwischen Angebot und Buchung fest. Begründe die Beziehungsart kurz. Es genügen die Klassen Fahrtenboerse, Angebot und Buchung. (4 Punkte)
Bewertung:
drei Methoden in
Fahrtenboersemit vollständiger Signatur: 1 PunktbuchungHinzufuegen(b: Buchung)inAngebot: 1 PunktKonstruktor
Buchung(mitfahrer: Nutzer, angefragtAm: Zeitpunkt)ohne Rückgabetyp: 1 PunktKomposition mit Begründung: Eine Buchung gehört zu genau einem Angebot, entsteht nur über dieses Angebot und ist ohne es sinnlos: 1 Punkt (eine Aggregation mit nachvollziehbarer Begründung ist ebenfalls richtig)
Aufgabe 3.2: Absatz nach Artikeln und Ofenprotokoll im Fahrradshop (Profilkompetenz)
(ca. 27 min Bearbeitungszeit)
Du bist Auszubildende*r im IT-Team der CSB-Rad GmbH in Bielefeld. Natalia Wróbel aus dem Controlling möchte wissen, welche Artikel sich in einem Zeitraum wie oft verkauft haben und an welchem Wochentag der Shop am meisten umsetzt. Außerdem liefert der Fertigungspartner Rahmenwerk OWL GmbH Messwerte aus seinem Einbrennofen, mit denen die Qualität der Pulverbeschichtung belegt werden soll. Folgende Klassen sind vorhanden:
Für alle Attribute gibt es öffentliche Getter.
Datumswerte kannst Du mit
<,<=und==vergleichen.d.getWochentag()liefert 1 für Montag bis 7 für Sonntag.Eine
Map<K, V>ordnet Schlüsseln Werte zu:put(k, v)legt einen Wert ab oder ersetzt ihn,get(k)liest ihn,containsKey(k)prüft, ob es den Schlüssel gibt; eine leere Map entsteht mitnew HashMap<K, V>(). In Pseudo-Python ist die Map ein Dictionary (m = {},m[k] = v,m[k],k in m).
Die Verkäufe liegen in der Liste verkaeufe vom Typ List<Verkauf> (Auszug, Preise netto):
| Index | datum | artikelNr | menge | einzelpreis |
|---|---|---|---|---|
| 0 | Mo 05.10.2026 | KET-PFL-01 | 3 | 8,40 |
| 1 | Mo 05.10.2026 | LIC-SET-01 | 1 | 68,07 |
| 2 | Di 06.10.2026 | SCH-BUE-01 | 2 | 62,18 |
| 3 | Mi 07.10.2026 | KET-PFL-01 | 5 | 8,40 |
| 4 | Fr 09.10.2026 | RAD-CITY-01 | 1 | 671,43 |
| 5 | Sa 10.10.2026 | LIC-SET-01 | 4 | 68,07 |
| 6 | Sa 10.10.2026 | KET-PFL-01 | 2 | 8,40 |
| 7 | Mo 12.10.2026 | SCH-BUE-01 | 1 | 62,18 |
a) Entwickle die Methode mengeJeArtikel(verkaeufe: List<Verkauf>, start: Datum, ende: Datum): Map<String, Integer>. Sie liefert für jede Artikelnummer, die im Zeitraum von start bis ende (beide eingeschlossen) verkauft wurde, die verkaufte Gesamtmenge. Die Liste soll dabei nur einmal durchlaufen werden. Gib das Ergebnis für den 05.10. bis 10.10.2026 an. (7 Punkte)
Funktion mengeJeArtikel(verkaeufe: List<Verkauf>, start: Datum, ende: Datum): Map<string, integer>
ergebnis: Map<string, integer> := new HashMap<string, integer>()
für jedes v in verkaeufe
wenn start <= v.getDatum() und v.getDatum() <= ende dann
nr: string := v.getArtikelNr()
wenn ergebnis.containsKey(nr) dann
ergebnis.put(nr, ergebnis.get(nr) + v.getMenge())
sonst
ergebnis.put(nr, v.getMenge())
Ende wenn
Ende wenn
Ende für
Rückgabe ergebnis
Ende mengeJeArtikel
Ergebnis: KET-PFL-01 → 10, LIC-SET-01 → 5, SCH-BUE-01 → 2, RAD-CITY-01 → 1. Der Verkauf vom 12.10. liegt außerhalb.
Bewertung: leere Map anlegen und zurückgeben 1 Punkt, Schleife über alle Verkäufe 1 Punkt, Zeitraum mit beiden Grenzen 1 Punkt, Fallunterscheidung „Schlüssel vorhanden?“ 1 Punkt, vorhandene Menge erhöhen statt überschreiben 1 Punkt, neuen Schlüssel mit der Menge anlegen 1 Punkt, Ergebnis 1 Punkt.
Eine Map erspart den Zwischenschritt, erst alle Artikelnummern zu sammeln: Der Schlüssel wird beim ersten Treffer angelegt.
b) Cem Sarıkaya hatte vor Deiner Lösung einen Entwurf geschrieben. Die Zeilen sind durchnummeriert, die erste Zeile ist der Methodenkopf.
Funktion mengeJeArtikel(verkaeufe: List<Verkauf>, start: Datum, ende: Datum): Map<string, integer>
ergebnis: Map<string, integer> := new HashMap<string, integer>()
zähle i von 1 bis verkaeufe.size() - 1
v: Verkauf := verkaeufe.get(i)
wenn start < v.getDatum() und v.getDatum() <= ende dann
wenn ergebnis.containsKey(v.getArtikelNr()) dann
ergebnis.put(v.getArtikelNr(), v.getMenge())
sonst
ergebnis.put(v.getArtikelNr(), v.getMenge())
Ende wenn
Ende wenn
Ende zähle
Rückgabe ergebnis
Ende mengeJeArtikel
ba) Führe den Entwurf mit den Beispieldaten und dem Zeitraum 05.10. bis 10.10.2026 durch. Gib die Map an, die er liefert, und markiere die Abweichungen zum Ergebnis aus a). (3 Punkte)
| i | Verkauf | im Zeitraum laut Zeile 5? | Map danach |
|---|---|---|---|
| – | Index 0 wird nicht gelesen | – | {} |
| 1 | 05.10. LIC-SET-01, 1 | nein (05.10. < 05.10. ist falsch) |
{} |
| 2 | 06.10. SCH-BUE-01, 2 | ja | SCH 2 |
| 3 | 07.10. KET-PFL-01, 5 | ja | SCH 2, KET 5 |
| 4 | 09.10. RAD-CITY-01, 1 | ja | SCH 2, KET 5, RAD 1 |
| 5 | 10.10. LIC-SET-01, 4 | ja | …, LIC 4 |
| 6 | 10.10. KET-PFL-01, 2 | ja, Wert ersetzt | SCH 2, KET 2, RAD 1, LIC 4 |
| 7 | 12.10. | nein | unverändert |
Abweichungen: KET-PFL-01 2 statt 10, LIC-SET-01 4 statt 5. Bewertung: Ablauf 2 Punkte, Abweichungen 1 Punkt.
bb) Nenne die drei Fehler des Entwurfs mit Zeilennummer und gib jeweils die korrigierte Zeile an. Erkläre, warum die Testdaten zwei dieser Fehler nicht auseinanderhalten können. (4 Punkte)
Zeile 3: Die Schleife beginnt bei 1, der erste Verkauf fehlt.
Zeile 5:
start <schließt den ersten Tag aus; richtig iststart <=.Zeile 7: Ist der Schlüssel schon vorhanden, wird die Menge ersetzt statt addiert.
Korrigierte Zeilen 3, 5 und 7:
zähle i von 0 bis verkaeufe.size() - 1
wenn start <= v.getDatum() und v.getDatum() <= ende dann
ergebnis.put(v.getArtikelNr(), ergebnis.get(v.getArtikelNr()) + v.getMenge())
Der Verkauf mit Index 0 fällt am 05.10., also auf den ersten Tag. Er fehlt wegen Zeile 3 und wegen Zeile 5; das Ergebnis zeigt nicht, welcher Fehler die Ursache ist. Ein guter Testfall trennt die Fehler, z. B. ein Verkauf am ersten Tag an Position 1 und einer an einem mittleren Tag an Position 0.
Bewertung: je Fehler mit Korrektur 1 Punkt, Erklärung 1 Punkt.
c) Entwickle die Methode staerksterWochentag(verkaeufe: List<Verkauf>): Integer. Sie summiert den Umsatz (Menge mal Einzelpreis) aller Verkäufe getrennt nach Wochentag in einem Array mit sieben Einträgen und liefert die Nummer des Wochentags mit dem höchsten Umsatz (1 = Montag). Welchen Wochentag liefert sie für die Beispieldaten, und wie aussagekräftig ist das Ergebnis? (6 Punkte)
Funktion staerksterWochentag(verkaeufe: List<Verkauf>): integer
umsatz: double[7] := [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
für jedes v in verkaeufe
index: integer := v.getDatum().getWochentag() - 1
umsatz[index] := umsatz[index] + v.getMenge() * v.getEinzelpreis()
Ende für
besterIndex: integer := 0
zähle i von 1 bis 6
wenn umsatz[i] > umsatz[besterIndex] dann
besterIndex := i
Ende wenn
Ende zähle
Rückgabe besterIndex + 1
Ende staerksterWochentag
Umsätze: Mo 155,45 €, Di 124,36 €, Mi 42,00 €, Do 0 €, Fr 671,43 €, Sa 289,08 €, So 0 €. Die Methode liefert 5 (Freitag).
Aussagekraft: Der Freitag liegt nur wegen eines einzigen Citybikes vorn; ohne diesen Verkauf wäre es der Samstag. Bei Daten aus gut einer Woche entscheidet ein Einzelverkauf über das Ergebnis; für eine Aussage braucht es mehrere Monate, und die Zahl der Verkäufe je Wochentag sollte mit betrachtet werden.
Bewertung: Array mit sieben Nullen 1 Punkt, Index aus dem Wochentag (minus 1) 1 Punkt, Umsatz aufsummieren 1 Punkt, Maximum mit Index suchen und als Wochentag (plus 1) zurückgeben 2 Punkte, Ergebnis mit Bewertung 1 Punkt.
d) Rahmenwerk OWL misst beim Einbrennen jede Minute die Objekttemperatur eines Rahmens. Die Messwerte liegen zeitlich geordnet im Array messwerte vom Typ Ofenmesswert[] vor. Laut Datenblatt des Pulvers muss die Temperatur an zwölf aufeinanderfolgenden Messungen mindestens 175 °C betragen.
Messwerte ab 10:00 Uhr (in °C): 165, 171, 176, 178, 177, 174, 176, 177, 179, 180, 181, 180, 179, 178, 177, 176, 175, 172, 168, 160
da) Entwickle die Methode beginnHaltephase(messwerte: Ofenmesswert[], mindest: Real, benoetigt: Integer): Zeitpunkt. Sie liefert den Zeitpunkt der ersten Messung der ersten Folge, in der benoetigt Messwerte hintereinander mindestens mindest erreichen, oder null, wenn es keine solche Folge gibt. Die Suche soll enden, sobald die Folge lang genug ist. (7 Punkte)
Funktion beginnHaltephase(messwerte: Ofenmesswert[], mindest: double, benoetigt: integer): Zeitpunkt
folge: integer := 0
i: integer := 0
solange i < laenge(messwerte) und folge < benoetigt
wenn messwerte[i].getTemperatur() >= mindest dann
folge := folge + 1
sonst
folge := 0
Ende wenn
i := i + 1
Ende solange
wenn folge < benoetigt dann
Rückgabe null
Ende wenn
Rückgabe messwerte[i - benoetigt].getZeit()
Ende beginnHaltephase
Endet die Schleife, weil die Folge lang genug ist, zeigt i auf den Messwert hinter der Folge. Die Folge beginnt deshalb bei i - benoetigt.
Bewertung: Zähler für die laufende Folge 1 Punkt, Schleife mit Index über das Array 1 Punkt, Abbruch, sobald benoetigt erreicht ist 1 Punkt, Zähler erhöhen bzw. zurücksetzen 2 Punkte, null ohne ausreichende Folge 1 Punkt, Startindex der Folge richtig berechnet 1 Punkt.
db) Was liefert beginnHaltephase für das Beispiel mit 175.0 und 12? Der Schichtleiter meint: „Elf von zwölf, das reicht.“ Nimm Stellung. (3 Punkte)
Die längste Folge reicht von 10:06 Uhr (176 °C) bis 10:16 Uhr (175 °C) und umfasst elf Messwerte; die erste Folge (10:02–10:04) hat drei. Die Methode liefert null (1 Punkt).
Stellungnahme (2 Punkte): Die Vorgabe des Pulverherstellers ist eine Mindestanforderung; darunter ist nicht sicher, dass die Beschichtung vollständig vernetzt und später haftet oder korrosionsbeständig ist. Der Rahmen gilt deshalb als nicht ordnungsgemäß eingebrannt und muss nach Herstellerangabe nachbehandelt oder gesperrt werden. Sinnvoll ist eine Warnung an den Ofen, sobald eine Haltephase zu kurz zu werden droht.
Aufgabe 3.3: Seitenweise Sessionliste und Technikrunde beim Barcamp (Profilkompetenz)
(ca. 29 min Bearbeitungszeit)
Du arbeitest im Orga-Team des Barcamps „Lernen.Digital.Leben 2027“ am Ratz und Rübe Berufskolleg mit. Die Barcamp-App zeigt alle eingereichten Sessions als Liste an und lädt sie dafür seitenweise vom Info-Server. Emre Aksoy, Leiter des Technikteams, braucht außerdem Hilfe bei der Überwachung der Anzeigegeräte und bei der Planung seiner Runden.
Für die Schnittstelle sind folgende Klassen vorhanden:
service.alleSessions()liefert alle Sessions in der Reihenfolge, in der die App sie anzeigt.JsonWandler.zuJson(liste)liefert die Sessions als JSON-Text,JsonWandler.fehler(text)einen JSON-Text mit einer Fehlermeldung.
Die App ruft sessionsAbrufen(seite, proSeite) auf. Es gilt:
Seite 1 enthält die ersten
proSeiteSessions, Seite 2 die nächsten und so weiter; die letzte Seite darf weniger enthalten.Ist
seitekleiner als 1 oderproSeitenicht zwischen 1 und 20, antwortet der Server mit Status 400.Gibt es die angefragte Seite nicht, antwortet er mit Status 404. Seite 1 gibt es immer, notfalls ohne Sessions.
Sonst antwortet er mit Status 200, den Sessions der Seite als JSON und der Kopfzeile
X-Total-Countmit der Gesamtzahl der Sessions.
aa) Zurzeit sind 23 Sessions eingereicht. Entscheide für jede Anfrage, mit welchem Status der Server antwortet und, bei Status 200, welche Indizes der Gesamtliste die Seite enthält. (3 Punkte)
| Anfrage | seite | proSeite |
|---|---|---|
| 1 | 1 | 10 |
| 2 | 3 | 10 |
| 3 | 4 | 10 |
| 4 | 0 | 5 |
| 5 | 2 | 25 |
| 6 | 5 | 5 |
| Anfrage | Status | Indizes |
|---|---|---|
| 1 | 200 | 0 bis 9 |
| 2 | 200 | 20 bis 22 (nur 3 Sessions) |
| 3 | 404 | – (es gibt nur 3 Seiten) |
| 4 | 400 | – |
| 5 | 400 | – |
| 6 | 200 | 20 bis 22 (5 Seiten, die letzte mit 3 Sessions) |
Je zwei richtige Anfragen 1 Punkt.
ab) Implementiere die private Methode seiteHolen(alle: List<Session>, seite: Integer, proSeite: Integer): List<Session>. Du kannst davon ausgehen, dass die Parameter bereits geprüft sind und die Seite existiert. (5 Punkte)
Funktion seiteHolen(alle: List<Session>, seite: integer, proSeite: integer): List<Session>
ergebnis: List<Session> := new List<Session>()
erster: integer := (seite - 1) * proSeite
grenze: integer := erster + proSeite
wenn grenze > alle.size() dann
grenze := alle.size()
Ende wenn
zähle i von erster bis grenze - 1
ergebnis.add(alle.get(i))
Ende zähle
Rückgabe ergebnis
Ende seiteHolen
Bewertung: Ergebnisliste anlegen und zurückgeben 1 Punkt, ersten Index aus Seite und Seitenlänge berechnen 1 Punkt, Grenze berechnen und auf die Listenlänge begrenzen 2 Punkte, Schleife mit Übernahme der Sessions 1 Punkt.
ac) Implementiere die öffentliche Methode sessionsAbrufen(seite: Integer, proSeite: Integer): HttpAntwort nach den oben genannten Regeln. Nutze die Methode aus ab). (7 Punkte)
Funktion sessionsAbrufen(seite: integer, proSeite: integer): HttpAntwort
wenn seite < 1 oder proSeite < 1 oder proSeite > 20 dann
Rückgabe new HttpAntwort(400, JsonWandler.fehler("seite oder proSeite ungültig"))
Ende wenn
alle: List<Session> := service.alleSessions()
seitenGesamt: integer := (alle.size() + proSeite - 1) div proSeite
wenn seite > 1 und seite > seitenGesamt dann
Rückgabe new HttpAntwort(404, JsonWandler.fehler("Seite " & seite & " gibt es nicht"))
Ende wenn
antwort: HttpAntwort := new HttpAntwort(200, JsonWandler.zuJson(seiteHolen(alle, seite, proSeite)))
antwort.setHeader("X-Total-Count", "" & alle.size())
Rückgabe antwort
Ende sessionsAbrufen
Die Zahl der Seiten ist eine aufgerundete Division. In Ganzzahlarithmetik gelingt sie mit (anzahl + proSeite - 1) div proSeite: 23 Sessions mit 10 je Seite ergeben \lfloor 32 / 10 \rfloor = 3 Seiten. Alternativ zählt man, ob (seite - 1) * proSeite kleiner als die Gesamtzahl ist.
Bewertung:
Parameter vor dem Datenzugriff prüfen, Status 400: 2 Punkte
Sessions über den Service holen: 1 Punkt
Seitenzahl richtig ermitteln und nicht vorhandene Seite mit 404 beantworten, Seite 1 ausgenommen: 2 Punkte
Erfolgsantwort mit Methode aus ab),
zuJsonund Kopfzeile: 2 Punkte
Für die Anzeigegeräte und die Raumplanung gibt es außerdem die Klasse Sessionplaner:
Anzeige.statusText()liefert die Raumnummer und „: keine Verbindung“, z. B. „Foyer: keine Verbindung“.TuerschildüberschreibtstatusText()und liefert die Raumnummer mit dem zuletzt gemeldeten Akkustand, z. B. „B.202: Akku 85 %“.InfomonitorüberschreibtstatusText()nicht.
ba) Am Morgen des Barcamps läuft im Sessionplaner der folgende Code; die Liste meldungen ist zu Beginn leer.
für jedes a in anzeigen
wenn nicht a.istErreichbar() dann
meldungen.add(a.statusText())
Ende wenn
Ende für
Die Liste anzeigen enthält diese Objekte:
| Position | Klasse | raumNr | akku | istErreichbar() |
|---|---|---|---|---|
| 0 | Tuerschild | A.104 | 12 | false |
| 1 | Infomonitor | Foyer | – | false |
| 2 | Tuerschild | B.202 | 85 | true |
| 3 | Infomonitor | Mensa | – | true |
| 4 | Tuerschild | C.110 | 4 | false |
Gib den Inhalt von meldungen nach dem Durchlauf an und begründe den zweiten Eintrag. (3 Punkte)
meldungen enthält „A.104: Akku 12 %“, „Foyer: keine Verbindung“ und „C.110: Akku 4 %“ (2 Punkte).
Der Infomonitor im Foyer überschreibt statusText() nicht. Zur Laufzeit wird für das Objekt die Methode seiner Klasse gesucht; weil Infomonitor keine eigene hat, wird die geerbte aus Anzeige ausgeführt. Für die Türschilder wird dagegen deren überschriebene Fassung aufgerufen, obwohl die Variable a den Typ Anzeige hat (1 Punkt).
bb) Ein Teammitglied schlägt vor, in der Schleife zu fragen, ob a ein Türschild ist, und den Text für Türschilder dort selbst zusammenzusetzen. Bewerte den Vorschlag. (2 Punkte)
Der Vorschlag funktioniert, ist aber schlechter: Die Schleife müsste jede Geräteart kennen und bei jeder neuen Art (etwa einem Beamer mit Lampenstunden) geändert werden; außerdem gelangt Wissen über den Aufbau des Türschilds in den Sessionplaner (1 Punkt). Mit der überschriebenen Methode entscheidet jedes Objekt selbst, welcher Text passt; neue Unterklassen funktionieren ohne Änderung der Schleife (1 Punkt).
c) Am Vorabend tauscht Emre die Akkus von vier E-Ink-Türschildern. Er startet im Orga-Büro A.010, geht immer zum nächstgelegenen noch nicht besuchten Türschild und kehrt am Ende ins Orga-Büro zurück (Nächster-Nachbar-Verfahren mit Rückkehr). Die Weglängen in Metern:
| von \ nach | A.104 | B.012 | B.202 | C.020 |
|---|---|---|---|---|
| A.010 (Orga-Büro) | 40 | 55 | 95 | 70 |
| A.104 | – | 60 | 65 | 110 |
| B.012 | 60 | – | 45 | 50 |
| B.202 | 65 | 45 | – | 80 |
ca) Ermittle Emres Runde und ihre Gesamtlänge einschließlich des Rückwegs. (3 Punkte)
| Schritt | Standort | Entfernungen zu den offenen Zielen | gewählt |
|---|---|---|---|
| 1 | A.010 | A.104: 40, B.012: 55, B.202: 95, C.020: 70 | A.104 (40 m) |
| 2 | A.104 | B.012: 60, B.202: 65, C.020: 110 | B.012 (60 m) |
| 3 | B.012 | B.202: 45, C.020: 50 | B.202 (45 m) |
| 4 | B.202 | C.020: 80 | C.020 (80 m) |
| 5 | C.020 | zurück zu A.010 | 70 m |
Runde A.010 → A.104 → B.012 → B.202 → C.020 → A.010 mit 295 m. Ablauf 2 Punkte, Länge 1 Punkt.
cb) Finde eine kürzere Runde und erkläre, warum das Verfahren sie nicht gefunden hat. (3 Punkte)
A.010 → A.104 → B.202 → B.012 → C.020 → A.010 mit 40 + 65 + 45 + 50 + 70 = 270 m (oder dieselbe Runde rückwärts) (2 Punkte).
Das Verfahren entscheidet in jedem Schritt nur nach dem kürzesten nächsten Weg (gierig, greedy). Von A.104 aus wählt es B.012, weil 60 m kürzer sind als 65 m, und muss dann später den langen Weg B.202 → C.020 (80 m) gehen. Den Rückweg berücksichtigt es bei keiner Entscheidung (1 Punkt).
cc) Wie viele verschiedene Runden müsste ein Programm bei 30 Türschildern prüfen, um sicher die kürzeste zu finden? Warum ist das Nächster-Nachbar-Verfahren trotzdem sinnvoll? (2 Punkte)
Bei festem Start gibt es 30! Reihenfolgen; weil jede Runde vorwärts und rückwärts gleich lang ist, sind es \frac{30!}{2} \approx 1{,}3 \cdot 10^{32} verschiedene Runden – nicht in vertretbarer Zeit prüfbar (1 Punkt). Das Nächster-Nachbar-Verfahren braucht nur etwa 30 \cdot 30 Vergleiche und liefert meist eine brauchbare, wenn auch nicht immer die kürzeste Runde (1 Punkt).
d) Im Sessionplaner enthält das Array raumNr die acht Räume (A.001, A.104, A.105, B.012, B.201, B.202, C.110, C.020). Das zweidimensionale Array belegung hat für jeden Raum eine Zeile (gleicher Index wie in raumNr) und für jeden der fünf Slots eine Spalte; ein Eintrag ist die Session oder null, wenn der Raum frei ist.
Entwickle die Methode freieRaeume(slot: Integer): List<String>, die die Raumnummern aller Räume liefert, die im angegebenen Slot frei sind. Was liefert freieRaeume(2), wenn im dritten Slot A.001, A.104, B.202 und C.110 belegt sind? (4 Punkte)
Funktion freieRaeume(slot: integer): List<string>
frei: List<string> := new List<string>()
zähle r von 0 bis laenge(raumNr) - 1
wenn belegung[r][slot] = null dann
frei.add(raumNr[r])
Ende wenn
Ende zähle
Rückgabe frei
Ende freieRaeume
freieRaeume(2) liefert A.105, B.012, B.201 und C.020 (der dritte Slot hat den Index 2).
Bewertung: Ergebnisliste anlegen und zurückgeben 1 Punkt, Schleife über alle Räume (erste Dimension) 1 Punkt, Zugriff mit Raum- und Slotindex und Vergleich mit null 1 Punkt, Raumnummer aus dem parallelen Array übernehmen und Ergebnis 1 Punkt.
Links und weitere Informationen
Objektorientierte Algorithmen: Methoden über Objektlisten (zugehöriger Artikel)
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Übungsaufgaben zu objektorientierten Algorithmen: Methoden über Objektlisten” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/algorithmen-objektorientiert-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/programmierung/programmiergrundlagen. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 28.10.2026.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
