• Keine Ergebnisse gefunden

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

N/A
N/A
Protected

Academic year: 2022

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

Copied!
6
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

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

Abgabe:7. November 2017, 13:00

xkcd: Margin

Randall Munroe (CC BY-NC2.5)

Checken Sie mit Eclipse wie bisher die neue Übungs-Vorlage aus. Beachten Sie, dass Sie mehrere unabhängige Programme im selben Eclipse-Projekt haben werden. Bevor Sie ein Programm starten, achten Sie deshalb darauf, dass Sie die richtige Datei im Package Explorer ausgewählt oder im Editor geöffnet haben.Vergessen Sie nicht, Ihren Programmcode zu kommentieren!

Aufgabe 1: Gipfel (Bonus!)

Achtung:Diese Aufgabe gibt Bonuspunkte (siehe “Leistungskontrolle”

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

a) In “Gipfel.java” finden Sie ein Programm, das eine Serie von Höhen (in Metern über Meer) aus der Datei “gipfelhoehen.txt” in dasint-Arrayhoeheneinliest. Dieses Array wird dann der MethodefindeGroessteErhebungübergeben, welche dieErhebungdes höchsten Gipfels ermittelt und zurück gibt. Ihre Aufgabe ist es, diese Methode zu implementieren.

EinGipfelist ein Punkt in der Höhenserie, bei dem beide direkt benachbarten Punkte tiefer liegen. Analog gibt es Talsohlen, welche definiert sind als Punkte, bei denen beide direkt benachbarten Punkte höher liegen. (Das heisst, dass Start- und Endpunkte der Serie weder als Gipfel noch als Talsohlen gelten.) Der Einfachheit halber sind alle Höhen in der Serie nicht-negativ und direkt benachbarte Punkte sind nie gleich hoch.

Die Erhebung, welche vonfindeGroessteErhebungzurückgegeben wird, ist nicht gleich der Höhe des Gipfels, sondern die Höhendifferenz zu der höhergelegenen benachbarten Talsohle.

Der “erhabenste” Gipfel ist also nicht derjenige, der die grösste Höhe in der Höhenserie hat, sondern derjenige, der die höchste Höhendifferenz aufweist. Um die Aufgabe zu vereinfachen, interessieren wir uns nur für Gipfel, von denen links und rechts eine Talsohle liegt. Die Talsohlen müssen dabeinichtdirekt neben dem Gipfel liegen. Falls kein solcher Gipfel in der Höhenserie vorkommt, oderhoehen==nullgilt, soll 0 zurückgegeben werden.

In der Höhenserie{2, 1, 2, 5, 4, 3, 4, 6, 5, 6}, beispielsweise, gibt es drei Talsohlen an den Positionen1,5und8, und zwei Gipfel an den Positionen3und7. Die Höhendifferenzen des ersten Gipfels zu seinen beiden benachbarten Talsohlen betragen 5−1=4 und 5−3=2,

(2)

somit ist die Erhebung des Gipfels 2. Der zweite Gipfel hat zu seinen beiden benachbarten Talsohlen die Differenzen 6−3 = 3 und 6−5 = 1, und somit eine Erhebung von 1. Damit sollte die MethodefindeGroessteErhebungfür diese Höhenserie 2 zurückgeben.

b) In der Datei “GipfelTest.java” finden Sie einen Test. Schreiben Sie weitere Tests um sicherzu- stellen, dass Ihre Implementierung richtig ist. Anschliessend committen Sie Ihre Lösung vor dem Abgabetermin.

Beachten Sie, dass wir nur die Methode findeGroessteErhebung bewerten. Was Sie mit Ihren Tests und dermain-Methode machen, wird nicht berücksichtigt. Bevor Sie Ihre Lösung committen, stellen Sie sicher, dass Sie die Methodensignatur (static int findeGroessteErhebung(int[]

hoehen)) nicht verändert haben.

Aufgabe 2: Datenanalyse mit Personen

In der letzten Übung haben Sie Körpergrössen analysiert. In dieser Aufgabe werten Sie einen Personen-Datensatz mit mehreren “Spalten” aus. Die Spalten enthalten Werte für Gewicht, Alter, Geschlecht, usw. Um einfach mit diesen Daten zu arbeiten, entwerfen Sie eine KlassePerson, welche alle Eigenschaften einer Person als Felder enthält. Weiter schreiben Sie ein Programm

“PersonenAnalyse.java”, welche die Personendaten aus einer Datei einliest und diese auswertet.

Sie finden wie gewohnt Tests für Teile des Programms im “test”-Ordner.

Die Daten befinden sich in der Datei “body.dat.txt”, welche wie folgt aufgebaut ist: Auf der ersten Zeile steht die Anzahl Datensätze in der Datei. Der Rest der Datei ist tabellarisch aufgebaut, wobei jede Zeile die Daten einer Person enthält. Die Beschreibung der Spalten und die Typen, den Sie für die Felder der KlassePersonverwenden sollen, sehen Sie in Tabelle1.

Spalte Beschreibung Java-Typ

0 Schulterbreite in cm double

1 Brusttiefe in cm double

2 Brustbreite in cm double

3 Alter in Jahren int

4 Gewicht in kg double

5 Grösse in cm double

6 Geschlecht (1: männlich,0: weiblich) boolean Tabelle1: Datenbeschreibung von “body.dat.txt”

a) Vervollständigen Sie die KlassePerson(in der Datei “Person.java”), indem Sie sie mit Feldern und Methoden zu ergänzen. Fügen Sie für jede Spalte im Datensatz ein Feld mit dem entspre- chenden Java-Typ hinzu und implementieren Sie den (schon vorhandenen) Konstruktor so, dass er diese Felder initialisiert.

Füllen Sie dann die Methodebeschreibung()so aus, dass sie einenStringzurück gibt, den die Person beschreibt. Beispielsweise könnte die Methode folgendes zurückgeben:

Person (m, 43 Jahre, 179.7 cm, 86.4 kg)

(3)

b) Als ersten Schritt der Datenanalyse sollten Sie die Daten einlesen und ein Array vonPerson- Objekten daraus erstellen. Implementieren Sie dazuPersonenAnalyse.liesPersonen()und rufen Sie die Methode mit dem richtigen Argument aus Ihrermain()-Methode auf.

c) Ihre erste Analyse soll “ungesunde” Personen anhand desBody-Mass-Index (BMI) finden.

Schreiben Sie eine MethodebodyMassIndex()in der Klasse Person, welche den BMI dieser Person nach folgender Formel berechnet:

BMI= Gewichtkg Grösse2m

Die Weltgesundheitsorganisation (WHO) definiert folgende Gewichtsklassifikation:

BMI<18.5 untergewichtig 18.5≤BMI<25.0 normalgewichtig 25.0≤BMI<30.0 übergewichtig 30.0≤BMI fettleibig

In der MethoddruckeUngesunde()sollen Sie nun alle Personen, welche nicht normalgewichtig sind, mithilfe des gegebenenPrintStreams ausgeben. Geben Sie für jede solche Person zuerst ihre beschreibung() und dann die entsprechende Gewichtsklasse aus. Eine Zeile in der Ausgabe könnte etwa so aussehen:

Person (m, 34 Jahre, 167.6 cm, 75.5 kg) ist übergewichtig

Um die Ausgabe anzusehen, rufen Sie die Methode druckeUngesunde() in der main()- Methode mitSystem.outals Argument auf. Ausserdem können Sie die Methode mit den Tests in “PersonenAnalyseTest.java” testen. Nachdem Sie überprüft haben, dass die Ausgabe korrekt ist, ändern Sie Ihr Programm schliesslich so ab, dass die Ausgabe in eine Datei “ungesund.txt”

geleitet wird.

d) Glücklicherweise sind die Daten ideal um ein weiteres wichtiges Problem zu lösen: Sie ermög- lichen uns, zu jeder Person einen geeigneten Trainingspartner fürs Fitnessstudio zu ermitteln.

Da die Geräte im Studio immer auf die Person eingestellt sein müssen, sollten Trainingspartner ähnliche “Dimensionen” aufweisen. Wir beschreiben die Ähnlichkeit von zwei Personenp1 und p2betreffend dieses Kriteriums alsPartner-Qualität Q(p1,p2), die wir wie folgt definieren:

gr¨ossenDiff(p1,p2) =gr¨osse(p1)−gr¨osse(p2)

brustDiff(p1,p2) =brustTiefe(p1)·brustBreite(p1)−brustTiefe(p2)·brustBreite(p2) schulterDiff(p1,p2) =schulterBreite(p1)−schulterBreite(p2)

Q(p1,p2) = 1

1+gr¨ossenDiff(p1,p2)2+ abs(brustDiff(p1,p2))

5 + schulterDiff(p1,p2)2 2

i) Implementieren Sie diese Formel in der MethodePersonenAnalyse.partnerQualitaet() und überprüfen Sie die Korrektheit mithilfe der Tests in “PersonenAnalyseTest.java”.

Folgende Methoden könnten dabei nützlich sein:Math.pow()undMath.abs().

(4)

ii) Schreiben Sie nun eine Methode druckeGuteTrainingsPartner(), welche die Qualität aller möglichen Paare berechnet. Sofern die Qualität eines Paares 0.8 übersteigt, sollen die Partner-Qualität, sowie die Beschreibungen und Gewichtsklassen beider Personen ausgegeben werden. Achten Sie darauf, dass kein Paar doppelt ausgegeben wird (eine bestimmte Person darf jedoch in mehreren Paaren auftreten). Ein Beispiel eines solchen Paares ist:

Person (m, 21 Jahre, 177.8 cm, 79.5 kg), übergewichtig Person (m, 19 Jahre, 177.8 cm, 76.6 kg), normalgewichtig Qualität: 1.0

Kennen Sie eine bessere Formel für Partner-Qualität?

Aufgabe 3: Black-Box Testing

Im letzten Übungsblatt haben Sie Testautomatisierung mit JUnit kennengelernt. In dieser Aufgabe sollen Sie nun Tests für eine Methode schreiben, deren Implementierung Sie nicht kennen.

Dadurch werden Sie weniger durch möglicherweise falsche Annahmen beeinflusst, die bei einer Implementierung getroffen wurden. Sie müssen sich also überlegen, wie sich jede fehlerfreie Implementierung verhalten muss. Diesen Ansatz nennt manBlack-Box Testing.

In Ihrem “U06”-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 void rotateArray(int[] values, int steps), welche Sie aus einer eigenen Klasse oder einem Unit-Test aufrufen können. Diese Methode “rotiert” ein int-Array um eine gegebene Anzahl Schritte.

Vereinfacht macht die MethoderotateArray()Folgendes: Eine Rotation mitsteps=1bedeutet, dass alle Elemente des Arrays um eine Position nach rechts verschoben werden. Das letzte Element wird dabei zum ersten. Mitsteps=2wird alles um zwei Positionen nach rechts rotiert, usw. Eine Rotation nach links kann mit einer negativen Zahl für steps erreicht werden. Das folgende Beispiel ist der erste, einfache Test, den Sie in der Datei “BlackBoxTest.java” finden:

int[] values = new int[] { 1, 2 };

int[] expected = new int[] { 2, 1 };

BlackBox.rotateArray(values, 1);

assertArrayEquals(expected, values);

Dieser Test prüft, dass das Array{ 1, 2 }nach einer Rotation mitsteps=1aussieht wie{ 2, 1 }.

Die Methode assertArrayEquals(expected, values)prüft, dass die beiden Arraysexpected undvaluesdie selben Elemente enthalten. Wenn nicht, schlägt der Test fehl.

Die genaue Definition vonrotateArraylautet wie folgt: Nach einem Aufruf ist das Element am Indexigleich dem Element, das zuvor am Index(i−steps) mod values.lengthwar, für alle i zwischen 0 und values.length−1, inklusive. “mod” steht für modulo und bezeichnet den Rest einer Ganzzahl-Division (sieheWikipedia). Mit diesem Wissen sollen Sie nun weitere Tests schreiben, die möglichst gut prüfen, ob sich eine Implementierung wunschgemäss verhält.

Überlegen Sie sich genau, was für die Parametervaluesundstepsangegeben werden kann, und wievaluesnach dem Aufruf vonrotateArray()aussieht. Der gegebene Test prüft beispielsweise

(5)

nur, dass bei einem Array mit zwei Elementen nach einer Rotation um1die Elemente vertauscht sind. Eine Implementierung, die ein Array einfach umkehrt, würde den Test auch bestehen.

Um die Stärke Ihrer Tests zu beurteilen, werden wir verschiedene, teilweise fehlerhafte Imple- mentierungen 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.

Aufgabe 4: EBNF Wiederholung

In dieser Aufgabe erstellen Sie wieder EBNF-Beschreibungen. Alle Beschreibungen werden in der Text-Datei “EBNF.txt” abgelegt, welche sich in Ihrem SVN Repository befindet.

Verwenden Sie “<=” als Zeichen für “ist definiert als”. Der Name der letzten Regel ist durch die Aufgabenbeschreibung vorgegeben, andere Namen können Sie frei wählen. Da reine Textdateien keine Kursivschrift unterstützen, stellen wir die Namen von Regeln zwischen<und>, also z.B.

<name>.

1. Erstellen Sie eine EBNF Beschreibung <xyz>, die als legale Symbole genau jene Wörter zulässt, in denen für jedesXentweder einYoder dreiZals Gruppe auftreten.

Beispiele legaler Symbole:"XY", "XXYZZZ", "", "XYYXZZZX"

2. Erstellen Sie eine EBNF Beschreibung <abc>, die als legale Symbole genau jene Wörter zulässt, die folgende Bedingungen erfüllen:

• Ein Wort besteht ausschliesslich aus den SymbolenA, B, C, X, Y, Z.

• Ein Wort beginnt mitAund endet mitB.

• Nach jedemXkommt entweder einYoder einZ.YundZkönnen nur direkt nach einem Xauftreten.

• Ckann nur in Paaren auftreten (CC) und kann nicht direkt nach einemZfolgen.

Beispiele legaler Symbole:"AB", "ACCB", "AXZB", "ABAB", "AXYXZXZXYCCB"

Aufgabe 5: Rekursion

In dieser Aufgabe zeichnen Sie einen Baum mittels Rekursion.

Wie auf dem Bild erkennbar, besteht der Baum aus mehreren zusammenhängenden Segmenten. Für jedes Segment gibt es zwei “Sub-Bäume”, einen gedreht im Uhrzeigersinn und einen gedreht im Gegenuhrzeigersinn.

Der Baum wird in mehreren Schritten gezeichnet. Jeder Schritt ist durch vier Parameter(x,y,α,l)bestimmt:

• Startpunkt (x,y) des aktuellen Segments

• Richtungαdes Segments

• Längeldes Segments

(6)

In jedem Schritt geschehen zwei Dinge:

1. Zeichnen des aktuellen Segments

2. Fallsl<10 endet die Rekursion und am Ende des Segments wird ein Blatt gemalt.

Anderenfalls werden rekursiv zwei weitere Zeichenschritte aufgerufen: Für den ersten Zeichenschritt werden die Argumentel0 =0.8·lundα0 =α+ π5, und für den zweiten die Argumentel00 =0.6·lundα00 =απ3 verwendet. Der Startpunkt für beide Zeichenschritte entspricht dem Endpunkt des aktuellen Segments.

Erstellen Sie ein Programm “Recursion.java”, welches einen Baum nach den zuvor beschriebenen Regeln in ein Fenster zeichnet.

1. Schreiben Sie eine rekursive MethodedrawTree, welche einen Zeichenschritt durchführt.

Zusätzlich zu den oben beschriebenen Parametern sollte diese Methode einen Parameter für dasWindow-Objekt haben.

2. Starten Sie die Rekursion in dermain-Methode mit den Argumentenx0 =SIZE/2,y0 =SIZE, l0=100,α0=Math.PI/2, wobeiSIZEdie Grösse des Fensters ist.

3. Experimentieren Sie mit den verschiedenen Zahlen, z.B. mit der Mindestlänge oder mit den Winkeländerungen.

Tipp: Sie können den Zeichenvorgang animieren, indem Sie zwischen Teil1und2jedes Zeichen- schrittesrefresh(100)auf dasWindow-Objekt aufrufen.

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