• Keine Ergebnisse gefunden

252-0027-00: Einführung in die Programmierung Übungsblatt 7

N/A
N/A
Protected

Academic year: 2022

Aktie "252-0027-00: Einführung in die Programmierung Übungsblatt 7"

Copied!
6
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

252 - 0027 - 00 : Einführung in die Programmierung Übungsblatt 7

Abgabe:14. November2017, 13:00

Checken Sie mit Eclipse wie bisher die neue Übungs-Vorlage aus. Vergessen Sie nicht, Ihren Programmcode zu kommentieren!

Aufgabe 1: Linked List

Bisher haben Sie Arrays verwendet, wenn Sie mit einer grösseren Anzahl von Werten gearbeitet haben. Ein Nachteil von Arrays ist, dass die Grösse beim Erstellen des Arrays festgelegt werden muss und danach nicht mehr verändert werden kann. In dieser Aufgabe implementieren Sie selbst eine Datenstruktur, bei welcher die Grösse im Vornherein nicht bestimmt ist und welche jederzeit wachsen und schrumpfen kann: Einelinked listoderverkettete Liste.

Eine verkettete Liste besteht aus mehreren Objekten, welche Referenzen zueinander haben. Für diese Aufgabe besteht jede Liste aus einem “Listen-Objekt” der KlasseLinkedIntList, welches die gesamte Liste repräsentiert, und aus mehreren “Knoten-Objekten” der KlasseIntNode, eines für jeden Wert in der Liste. Die Liste heisst “verkettet”, weil jedes Knoten-Objekt ein Feld mit einer Referenz zum nächsten Knoten in der Liste enthält. DasLinkedIntList-Objekt schliesslich enthält eine Referenz zum ersten und zum letzten Knoten und hat ausserdem ein Feld für die Länge der Liste.

IntNode

value: 1 next :

IntNode

value: 3 next :

IntNode

value: 3 next :

IntNode

value: 7 next :

LinkedIntList

first:

last : size : 4

Abbildung1: Verkettete Liste mit Werten1,3,3,7.

(2)

Abbildung 1zeigt eine Liste, welche die Werte1,3,3,7enthält. Beachten Sie, dass dasnext- Feld des letzten Knotens in der Liste auf kein Objekt zeigt, d.h. den Wertnullenthält. Ausserdem wird eine leere Liste so repräsentiert, dass beide Felderfirstundlast den Wertnullenthalten (undsizegleich0ist).

a) Schreiben Sie die KlassenLinkedIntListundIntNode, welche zusammen eine verkettete Liste vonints ergeben. Erstellen Sie die Klassen wie in Übung2und fügen Sie die benötigten Felder hinzu. Zusätzlich sollen Sie der KlasseLinkedIntListeineaddLast()-Methode hinzufügen, welche einenint-Wert entgegen nimmt und diesen am Ende der Liste anhängt.

Erstellen Sie dann ein Programm Echo, welches vom Benutzer int-Werte entgegen nimmt, diese in einerLinkedIntListspeichert und zum Schluss alle Werte in der Liste wieder ausgibt.

Das Programm soll solange Werte einlesen, bis der Benutzer eine ungültige Eingabe macht.

Verwenden Sie dazuScanner.hasNextInt().

Um alle Werte auszugeben, soll Ihr Programm von Knoten zu Knoten “springen”, angefangen beim ersten Knoten und solange, bis das Ende der Liste erreicht d.h. der nächste Knoten gleich nullist. Sie können folgendes Code-Stück dafür verwenden:

for(IntNode n = list.first; n != null; n = n.next) { ... }

b) Um dieLinkedIntList-Klasse benutzerfreundlicher zu machen, erweitern Sie sie um folgende Methoden:

Name Parameter Rückg.-Typ Beschreibung

addFirst int value void Fügt einen Wert am Anfang der Liste ein removeFirst int Entfernt den ersten Wert und gibt ihn zurück removeLast int Entfernt den letzten Wert und gibt ihn zurück

clear void Entfernt alle Wert in der Liste

isEmpty boolean Gibt zurück, ob die Liste leer ist

get int index int Gibt den Wert an der Stelleindexzurück set int index,int value void Ersetzt den Wert an der Stelleindexmitvalue toArray int[] Gibt alle Werte in einem neuen Array zurück Einige dieser Methoden dürfen unter gewissen Bedingungen nicht aufgerufen werden. Zum

Beispiel darfremoveFirst()nicht aufgerufen werden, wenn die Liste leer ist, oderget()darf nicht aufgerufen werden, wenn der gegebene Index grösser oder gleich der aktuellen Länge der Liste ist. In solchen Situationen soll sich Ihr Programm mit einer Fehlermeldung beenden.

Verwenden Sie folgendes Code-Stück dafür:

if(condition) {

Errors.error(message);

}

Ersetzen Siecondition mit der Bedingung, unter welcher das Programm beendet werden soll, undmessage mit einer hilfreichen Fehlermeldung. DieErrors-Klasse befindet sich bereits in Ihrem Projekt, aber Sie brauchen sie im Moment nicht zu verstehen.

(3)

Aufgabe 2: Unit-Tests für die Linked List

Um sicher zu gehen, dass Sie alleLinkedIntList-Methoden korrekt implementiert haben, schrei- ben Sie in dieser Aufgabe Unit-Tests dafür.

a) Am einfachsten erstellen Sie einen JUnit-Test für die LinkedIntList-Klasse, indem Sie im Package Explorer die Klasse rechtsklicken undNew→ JUnit Test Caseauswählen. Im Dialog, ändern Sie den Eintrag beiSource foldervon “.../src” auf “.../test” und klicken SieNext. Wählen Sie alle Methoden derLinkedIntList-Klasse aus und klicken SieFinish. Sie sollten nun eine neue KlasseLinkedIntListTestmit (fast) leeren Test-Methoden vorfinden.

b) Schreiben Sie jetzt die Tests. Der Ablauf eines einzelnen Tests könnte ungefähr so aussehen:

1) Erstellen einerLinkedIntList

2) Ändern der Liste, so dass sie sich im gewünschten Ausgangs-Zustand befindet 3) Aufrufen der zu testenden Methode auf der Liste (evtl. mit bestimmten Argumenten) 4) Überprüfen des Rückgabewertes und/oder des Ziel-Zustands der Liste

Überlegen Sie sich für jede Methode interessante Ausgangs- und Zielzustände und Methoden- Argumente. Denken Sie vor allem an Spezialfälle, z.B. wenn die Liste leer ist oder genau einen Wert enthält. Zögern Sie nicht, auch für das Testen zusätzliche Hilfs-Methoden zu schreiben, um Code-Duplizierung zu minimieren.

Benutzen Sie zum Überprüfen die assertXxx()-Methoden, welche Sie schon in früheren Übungen gesehen haben. DieDokumention derAssert-Klassevon JUnit enthält eine Liste von Methoden, welche Sie verwenden können. Ein möglicher Test, deraddFirst()testet, könnte z.B. so aussehen:

LinkedIntList list = new LinkedIntList();

list.addFirst(1);

list.addFirst(2);

list.addFirst(3);

assertArrayEquals(new int[]{3, 2, 1}, list.toArray());

c) Lassen Sie die Unit-Tests schliesslich laufen und beheben Sie die Fehler, die aufgedeckt wurden.

Wenn Sie das Gefühl haben, dass alles korrektund alles getestetist, können Sie den Test aus dem Anhang A (siehe unten) in IhreLinkedIntListTest-Klasse reinkopieren und ausführen.

Dieser testet nicht die gesamte Funktionalität der Liste, aber sollte einige “offensichtliche”

Fehler aufdecken. Sollte dies der Fall sein, gehen Sie nochmals zurück und schreiben Sie mehr Tests!

Aufgabe 3: Dominator (Bonus!)

Achtung: Diese Aufgabe gibt Bonuspunkte (siehe “Leistungskontrolle” im www.vvz.ethz.ch).

Die Aufgabe muss eigenhändig und alleine gelöst werden. Die Abgabe erfolgt wie gewohnt per Commit in Ihrem SVN Repository. Verbindlich ist der letzte Commit vor dem Abgabetermin.

Im letzten Übungsblatt haben SieBlack-Box Testingkennengelernt. Wie in der letzten Aufgabe sollen Sie wieder Tests für eine Methode schreiben, deren Implementierung Sie nicht kennen.

(4)

In Ihrem “U07”-Projekt befindet sich eine “blackbox.jar”-Datei, welche eine kompilierte Klasse BlackBoxenthält. Den Code dieser Klasse können Sie nicht sehen, aber sie enthält eine Methode int[] dominators(int[] elevations), welche Sie aufrufen können.

Die Methodedominatorshat den Parameterelevations. Das Arrayelevationsenthält die Höhenwerte (in Metern über Meer) für eine Serie von Punkten. Für jeden Punkt P (ein Index in elevations) berechnet die Methode, durch welchen anderen Punkt er dominiert wird. Der Rückgabewert ist ein Array, hier mitresultbezeichnet, welches für jeden PunktPdie Position (Index imelevations-Array) eines Dominators vonPenthält. Fallselevations nullist, ist auch result null.

EinDominator Deines PunktesPhat von allen Punkten, welche höher alsPliegen, die kleinste (horizontale) Distanz zu P. Falls zwei solche Punkte existieren, ist der höhere der beiden der einzige Dominator. Falls beide dieser Punkte gleich hoch sind, gibt es zwei mögliche Dominatoren.

Falls kein Dominator für Pexistiert, enthältresult[P]die Zahl-1.

Ein Beispiel finden Sie in der Datei “BlackBoxTest.java” in Ihrem Projekt. Der gegebene Test testSimple()übergibt als Argument die Höhenserie{3, 1, 2, 5, 3, 6, 5, 6}. Die Methode dominatorssollte nun entwederresult={3, 0, 3, 5, 5, -1, 5, -1}oderresult={3, 0, 3, 5, 5, -1, 7, -1}zurückgeben. Andernfalls enthält die Implementierung einen Fehler.

Der zweite gegebene Test testReturnsNull() prüft, dass die dominators-Methode null zurück gibt, wennnullals Argument übergeben wird.Dieser Test schlägt für die gegebeneBlackBox- Implementierung fehl.Damit zeigt dieser Test, dass sich diese Implementierung nicht vollständig an die obige Spezifikation hält. Da Sie nur diese eine Implementierung zur Verfügung haben, wird dieser Test auch zum Zeitpunkt der Abgabe fehlschlagen.

Schreiben Sie nun solange weitere Tests (in “BlackBoxTest.java”), bis sie zuversichtlich sind, dass Ihre Tests die Spezifikation genügend abdecken. Um die Stärke Ihrer Tests zu beurteilen, werden wir verschiedene, teilweise fehlerhafteBlackBox-Implementierungen mithilfe Ihrer Tests prüfen. Je mehr Fehler Ihre Tests aufdecken, desto besser. Tests sollten fehlschlagen, falls die Implementierung fehlerhaft ist, und erfolgreich durchlaufen, falls keine Fehler vorhanden sind.

Warnung: Da Unit-Tests generell höchstens einige Sekunden dauern, werten wir Tests, die länger als eine Minute dauern, als fehlerhaft. Sie können davon ausgehen, dass keine derBlackBox- Implementierungen Endlosschleifen enthalten.

Aufgabe 4: Self-avoiding Random Walks

xkcd: Random Numberby Randall Munroe (CC BY-NC2.5)

In dieser Aufgabe simulieren Sie das Schicksal eines Wolfs, der sich genau in der Mitte einer Stadt befindet und aus dieser ausbrechen will. Die Stadt besteht aus 2×NStrassen, die in einem regelmässigen Gitter an- geordnet sind. NStrassen verlaufen in der West-Ost Richtung,Nin der Nord-Süd Richtung. (Nist unge- rade und > 1.) Die Stadt kann (für diese Aufgabe) also vollständig durch die N×N Kreuzungen der Strassen beschrieben werden.

An jeder Kreuzung entscheidet der Wolf, in welche Richtung er fliehen will. Wenn der Wolf an der Kreuzung(i,j)steht, so kann er (dank seiner feinen Nase) feststellen, welche der Nachbar-

(5)

Kreuzungen(i+1,j),(i−1,j),(i,j+1), und(i,j−1)er schon besucht hat1. Eine einmal besuchte Kreuzung wird nicht nochmal besucht, d.h., der Wolf wählt zufällig unter den Richtugen, die ihn zu einer neuen, noch nicht besuchten Kreuzung führen. Wenn der Wolf den Stadtrand (d.h. die 1. oder die N. Strasse in nord-südlicher oder west-östlicher Richtung) erreicht hat, ist die Flucht erfolgreich verlaufen. Wenn der Wolf an eine Kreuzung kommt, von der aus er keine unbesuchte Kreuzung erreichen kann, dann ist die Flucht zu Ende und der Wolf wird (entsprechende Bewilligung vorausgesetzt) von den Jägern erschossen. Abbildung 2illustriert dies anhand von 5×5 und 7×7 Städten.

Wolf

Abbildung2: Wolf in der Stadt. Ausganglage, erfolgreiche Flucht und fehlgeschlagene Flucht

a) Schreiben Sie ein ProgrammRandomWalks, welches die Flucht des Wolfes simuliert. Sie können die Grösse der Stadt (N) sowie die Anzahl der Simulationen von der Konsole einlesen oder fest in zwei Variablen vorgeben. Nach der Simulation soll Ihr Programm ausgeben, in wieviel Prozent der Fälle der Wolf aus der Stadt fliehen konnte. Ausserdem, wie lang im Durchschnitt der Pfad war, der es einem Wolf erlaubte zu fliehen und wie lang (im Durchschnitt) der Pfad war, wenn der Wolf nicht aus der Stadt fliehen konnte. Die Länge des Pfades wird durch die Anzahl der besuchten Kreuzungen bestimmt, inklusive der Kreuzung, an welcher der Wolf startete.

Tipps: Verwenden Sie ein2-dimensionales Array vonbooleans, um sich die bereits besuchten Kreuzungen zu merken. Um per Zufall eine Richtung zu wählen, wird sich die Methode Random.nextInt(int)als nützlich erweisen.

Experimentieren Sie mit Ihrem Programm und vergleichen Sie z.B. die Wahrscheinlichkeit einer Flucht aus einer 9×9 Stadt mit der einer grösseren Stadt. Diese Simulation ist ein einfaches Beispiel für das Problem der “self-avoiding-paths” (der Pfade, die sich nicht kreuzen), welches eine Abstraktion für viele interessante Probleme aus Chemie, Pharmazie, Biologie und anderen Gebieten ist. (Nach Sedgewick & Wayne, Einführung in die Programmierung mit Java.)

1Er hat mindestens eine dieser Kreuzungen im vorherigen Schritt besucht um zu(i,j)zu kommen.

(6)

b) Nun sollen Sie die gelaufenen Pfade auf ein Fenster zeichnen. Falls ein Pfad erfolgreich war, malen Sie ihn in grün, ansonsten in rot.

Dazu müssen Sie sich den Pfad während der Simulation in einer LinkedIntListmerken und in einem zweiten Schritt (wenn Sie wis- sen, ob der Pfad erfolgreich war) in der richtigen Farbe zeichnen.

Jeden Schritt des Wolfs können Sie alsintkodiert der Liste hinzufü- gen, beispielsweise kodiert als0=Norden,1=Osten, usw. Es ist Ihnen überlassen, ob Sie die Pfade schrittweise (animiert) zeichnen, oder jeden Pfad auf einmal.

Anhang: Stichproben-Test für die Linked List

@Test

public void testRandom() {

Random rand = new Random(42);

LinkedIntList ll = new LinkedIntList();

for(int n = 0; n < 9721; n++) { int choice = rand.nextInt(6);

int value = rand.nextInt();

if(choice == 0)

ll.addFirst(value);

else if(choice == 1) ll.addLast(value);

else if(choice == 2 && !ll.isEmpty()) ll.removeFirst();

else if(choice == 3 && !ll.isEmpty()) ll.removeLast();

else if(choice == 4 && !ll.isEmpty()) ll.set(rand.nextInt(ll.size), value);

else if(choice == 5 && value % 5 == 0) ll.clear();

}

String msg = "There is a bug in your LinkedIntList";

assertFalse(msg, ll.isEmpty());

assertEquals(msg, 5, ll.size);

int[] expect = new int[]{-1759285598, -424345731, -1746103561, -1623993329, -1831395423};

assertArrayEquals(msg, expect, ll.toArray());

}

Referenzen

ÄHNLICHE DOKUMENTE

Ihr Programm muss diese Bedingung nicht zwingend testen, Sie können aber eine Überprüfung implementieren. Wenn zahl diese Bedingung nicht erfüllt, dann ist das Ergebnis des

Schreiben Sie ein Programm “Zahlen.java”, das einen String, der eine Anzeige kodiert, einliest und die kodierte Zahl als

In der Übungs-Vorlage finden Sie das Programm “Perpetual- Calendar.java”, welches für jedes (gültige) Datum den Wochentag berechnet. Leider enthält das Programm noch Fehler, die

Das Spiel besteht aus einem Ball und aus zwei Spielern, welche je einen vertikalen Balken kontrollieren und versuchen, den Ball im Spiel zu halten. Wenn der Ball das Spiel

Da beim Anpassen einer Folge für einen Wahlkreis die Folge für eine Partei geändert werden kann, wird dieses Verfahren wiederholt, bis die Summe der gerundeten Bruchteile von Sitzen

Beachten Sie, dass dafür die Klasse, welche Sie für die Elemente der Kollektion verwenden, das Interface Comparable&lt;T&gt; (T sollte die Klasse selber sein), und damit auch

Eclipse hilft Ihnen dabei, indem es anzeigt, wo die Fehler sind (und eine mehr oder weniger hilfreiche Fehlermeldung dazu ausgibt), aber Sie müssen selber herausfinden, was das

Eclipse hilft Ihnen dabei, indem es anzeigt, wo die Fehler sind (und eine mehr oder weniger hilfreiche Fehlermeldung dazu ausgibt), aber Sie müssen selber herausfinden, was das