Beruflich Dokumente
Kultur Dokumente
Datei Der Dstne
Datei Der Dstne
Lösungsvorschlag 8.1
Durch Aufruf der resize()-Methode kann das Quadrat derart verändert werden, dass es
sich um kein Quadrat mehr handelt. Obwohl also jedes Quadrat logisch ein Rechteck ist,
ist die Vererbungsbeziehung hier dennoch eine fragliche Modellierung. Mögliche Lösungen:
1
20 public void f(B<A> a) { System.out.println("C.f(B<A>)"); a.f(t); }
21 }
22
29 a.f(b1); // Aufruf 1
30 a.f(b2); // Aufruf 2
31
Geben Sie für jeden der markierten Aufrufe die Ausgabe an. Gehen Sie davon aus, dass
nur ein Aufruf im Programm vorhanden ist; die anderen seien jeweils auskommentiert.
Es kann jeweils auch ein Compiler- oder Laufzeitfehler auftreten. Geben Sie bei einem
Laufzeitfehler an, wo genau bzw. wieso dieser auftritt. Begründen Sie bei Aufruf 3 kurz
das Verhalten des Java-Compilers anhand eines Beispiels.
Lösungsvorschlag 8.2
1.
1 A.f(A)
2 A.f(A)
3 C.f(A)
2.
1 A.f(B)
2 A.f(A)
3 C.f(A)
3. Die Zuweisung ist nicht möglich, da generische Typen invariant sind. Stellen wir uns
vor, wir hätten eine Liste von Hasen, die wir in eine Liste von Säugetieren casten:
2
Wäre dies erlaubt, könnte man durch säugetiere.add(new Penguin()) einen Pin-
guin in eine Liste von Hasen einfügen.
import java.io.*;
public class ExceptionTest {
public static void main (String[] args) {
try {
Exception
// ...
}
catch (EOFException e) {
System.out.println("EOFException");
IOException }
catch (IOException e) {
System.out.println("IOException");
}
EOFException FileNotFoundException catch (Exception e) {
System.out.println("Exception");
}
System.out.println("ENDE");
}
}
1. An der durch „...“ gekennzeichneten Stelle im try-Block stehe ein Programm-
stück, durch das Exceptions vom Typen EOFException, IOException oder aber
FileNotFoundException geworfen werden können.
Was wird bei Ausführung der main-Methode ausgegeben, falls dabei im try-Block
i) als erstes eine Ausnahme vom Typ EOFException geworfen wird,
ii) als erstes eine Ausnahme vom Typ FileNotFoundException geworfen wird,
oder
iii) gar keine Ausnahme geworfen wird?
2. Was wird bei Ausführung der main-Methode ausgegeben, falls dabei im try-Block
als erste Ausnahme eine Division durch 0 auftritt?
Lösungsvorschlag 8.3
1. i) EOFException
ENDE
ii) IOException
ENDE
3
iii) ENDE
2. Exception
ENDE
wobei f0 = 4.
• Schreiben Sie ein Programm, das nach Eingabe des Index n die Annäherung fn für
Pi rekursiv berechnet und ausgibt.
• Schreiben Sie ein Programm, das abhänig von einem Schwellwert die Anzahl Schrit-
te n berechnet, so dass:
|π 0 − π| <
wo π 0 ist die berechnete Annäherung von π. Führen Sie Ihre Implementierung einmal
mit = 0.01 und einmal mit = 0.001 aus.
• Nach wievielen Schritten ist die Annäherung π 0 auf die ersten sieben Nachkommas-
tellen genau?
Lösungsvorschlag 8.5
Zur Berechnung kann folgendes angenommen werden |π 0 − π| < | 2∗(n+1)+1
4
|. Sonst kann
aber auch die Java Konstante Math.PI genommen werden. Um Stackoverflows zu ver-
meiden man kann: a) Stack größer machen oder b) Iterativ implementieren (s. Code).
1
Sehe http://de.wikipedia.org/wiki/Quersumme
4
Aufgabe 8.6 (P) Rekursion: Binomialkoeffizient
Der Binomialkoeffizient nk gibt an, auf wieviele verschiedene Arten man k Elemente aus
einer Menge von n verschiedenen Elementen auswählen kann (ohne Zurücklegen und ohne
Beachtung der Reihenfolge).
n−1 n−1 0
! ! ! ! ! !
n n n
Für 0 ≤ k ≤ n gilt: = + ; = 1; = =1
k k−1 k 0 n 0
Die Hausaufgabenabgabe erfolgt über Moodle. Bitte geben Sie Ihren Code als UTF8-
kodierte (ohne BOM) Textdatei(en) mit der Dateiendung .java ab. Geben Sie keine
Projektdateien Ihrer Entwicklungsumgebung ab. Geben Sie keinen kompilierten Code
ab (.class-Dateien). Sie dürfen Ihren Code als Archivdatei abgeben, dabei allerdings
ausschließlich das ZIP-Format nutzen. Achten Sie darauf, dass Ihr Code kompiliert.
Hausaufgaben, die sich nicht im vorgegebenen Format befinden, werden nur mit Punkt-
abzug oder gar nicht bewertet.
Aufgabe 8.7 (H) Mathematische Ausdrücke [3 Punkte]
In dieser Aufgabe sollen auf der Grundlage der in der Vorlesung behandelten Klassen-
hierarchie mathematische Ausdrücke in Form von Ausdrucksbäumen repräsentiert und
berechnet werden. Diese mathematischen Ausdrücke sollen zusätzlich zu den bereits im-
plementierten arithmetischen Ausdrücken (binäres +, −, ∗, /; unäres −) nun auch logische
Operatoren (binäres und (∧), oder (∨); unäre Negation (¬)) umfassen. Ausgangspunkt
hierzu ist die abstrakte Klasse Expression, die einen (abstrakten) mathematischen Aus-
druck repräsentiert, der sowohl arithmetischer als auch logischer Natur sein kann. Misch-
formen zwischen arithmetischen und logischen Operatoren sind zunächst nicht erlaubt (s.
nächste Aufgabe). Zusätzlich zur abstrakten Oberklasse sollen zwei abstrakte Unterklas-
sen implementiert werden, die binäre Operationen (Klasse BinOp) und unäre Operationen
(Klasse UnOp) repräsentieren. Außerdem soll es eine konkrete Unterklasse für Konstanten
geben (Klasse Const), die sowohl Integers als auch Booleans repräsentieren können
muss.
Die abstrakte Oberklasse Expression soll lediglich über die abstrakte Methode evaluate()
und die (abstrakte oder nicht abstrakte) Methode toString() verfügen, die jeweils erst in
den Unterklassen eine Implementierung erhalten. Die Methode evaluate() wertet einen
(arithmetischen oder logischen) Ausdruck aus und gibt das Ergebnis zurück2 .
2
In einer alten Version wurde gefordert, das Ergabnis auf der Konsole auszugeben. Dies macht keinen
Sinn, gibt aber auch keinen Abzug.
5
1. Machen Sie sich klar, dass in dieser Aufgabe gleichzeitig zwei Arten von Expressions
behandelt werden müssen, nämlich arithmetische (mit Integers parametriert) und
logische (mit Booleans parametriert). Benutzen Sie deshalb bei der Definition von
Expression sowie deren Unterklassen einen entsprechenden Typparameter.
Definieren Sie dann die drei genannten abstrakten und eine konkrete Klasse und
implementieren Sie die jeweiligen Konstruktoren. Beachten Sie, dass Konstanten nun
Integers oder Booleans sein können. Beachten Sie auch, dass abstrakte Klassen
durchaus über Konstruktoren verfügen können und dass, wenn Konstruktoren in
einer abstrakten Klasse C explizit implementiert sind, Sie in den Unterklassen von
C ggf. explizite Konstruktoren definieren müssen, die den Konstruktor von C explizit
als erste Zeile aufrufen.
2. Spezialisieren Sie dann für jeden arithmetischen (+, -, *, /) und jeden logischen (∧,
∨, ¬) Ausdruck die abstrakten Klassen BinOp und UnOp in jeweils eine konkrete
Unterklasse. Überlegen Sie sich, wie Sie die Konstruktoren dieser Klassen möglichst
einfach halten können.
Implementieren Sie eine der beiden Möglichkeiten, sodass Sie danach mit der Metho-
de evaluate() beliebige arithmetische oder logische Ausdrücke berechnen können.
Beispiel:
6
5. Betrachten Sie das in Abbildung 1 dargestellte Beispiel und schreiben Sie eine
main-Methode in einer Klasse ATest, die mindestens drei weitere Aufrufbäume in-
stanziiert. Die Aufrufbäume sollen jeweils aus mindestens fünf Objekten vom Typ
Expression bestehen. Testen Sie auf diesen Aufrufbäumen die Methoden evaluate()
und toString().
*" &&"
Lösungsvorschlag 8.7
Punkteverteilung:
1. 0.5 Punkte
2. 0.5 Punkte
3. 1 Punkte
4. 0.5 Punkte
5. 0.5 Punkte
7
Die Aufrufbäume sollen jeweils aus mindestens fünf Objekten vom Typ ZAExpression be-
stehen. Testen Sie auf diesen Aufrufbäumen die Methoden evaluate() und toString().
Beispiel:
=="
*" 9"
3" +"
1" 2"
Lösungsvorschlag 8.8
Bewertungshinweise:
• Diese Aufgabe war leider über lange Zeit mit einem fehlerhaften Beispiel online,
welches nur einen Typparameter verwendet hat. Studis, die sich darauf beziehen,
sind dafür keine Punkte abzuziehen.
8
Aufgabe 8.9 (H) PageRank Rekursiv [6 Punkte]
Ziel dieser Aufgabe ist die Implementierung des PageRank Algorithmus, der durch Google
allgemeine Bekanntheit erlangt hat. PageRank bewertet dabei nicht die Ähnlichkeit einer
Suchanfrage zu den erfassten Dokumenten. Stattdessen ist PageRank ein Verfahren, mit
dem die verschiedenen Seiten (bzw. Dokumente) an Hand ihrer Struktur bewertet bzw.
gewichtet werden. Hierzu wird jedem Dokument ein Gewicht zugeteilt, das sich aus der
Linkstruktur zwischen den Dokumenten berechnet. PageRank analysiert also alle ein- und
ausgehenden Links der Dokumente und gewichtet die einzelnen Dokumente auf Grundlage
dieser Links. Das Grundprinzip dabei lautet: je mehr Links auf ein Dokument verweisen,
desto höher ist das Gewicht dieses Dokumentes. Je höher dabei das Gewicht des verwei-
senden Dokumentes ist, desto größer ist auch das Gewicht der Seite auf die verwiesen
wird. Dokumente auf die von vielen anderen Dokumenten verwiesen wird haben somit ein
größeres Gewicht und damit eine höhere Popularität.
Implementieren Sie daher die rekursive Methode
aufgerufen werden, welche so zu implementieren ist, dass sie die PageRank-Werte aller
Dokumente berechnet und dabei die zu übergebenen Parameter entweder weiterreicht
oder, sofern notwendig, sinnvoll initialisiert und jeweils übergibt.
Die folgenden Ausführungen zu PageRank beruhen auf den Ausführungen der Webseite
"PageRank Algorithm - The Mathematics of Google Search"3 .
Das Prinzip des PageRank-Algorithmus wird im Folgenden an Hand eines Beispiels er-
klärt. Hierfür gehen wir davon aus, dass es vier Dokumente A, B, C und D gibt, deren
Fließtext die folgenden Links enthält:
A B C D
link:B link:C link:A link:C link:D link:D link:C
Hiermit ergibt sich die Linkstruktur aus Abbildung 3a.
3
http://www.math.cornell.edu/∼mec/Winter2009/RalucaRemus/Lecture3/lecture3.html
9
A B
C D
(a) Linkstruktur
Abbildung 3
Jedes Dokument kann also auf andere Dokumente verweisen, woraus sich die Verlinkungs-
matrix C wie folgt ergibt:
A B C D
0 1 0 0 A
1 0 0 0 B
C=
1 1 0 1 C
0 1 1 0 D
Jede Matrixzelle ci,j enthält hier die Information, ob eine Verlinkung von Dokument j auf
Dokument i vorliegt (1) oder nicht (0). Insofern enthält eine Spalte die ausgehenden und
eine Zeile die eingehenden Verlinkungen pro Dokument.
Beachten Sie: Verweist ein Dokument auf kein anderes Dokument (d.h. das Dokument
hat 0 ausgehende Links), so wird dieses Dokument so behandelt als ob es Links zu allen
anderen Dokumenten hätte.
Zusätzlich wird ein sogenannter Dämpfungsfaktor d, ein Wert zwischen 0 und 1, einge-
führt. Dieser ist notwendig, da nicht notwendigerweise alle Dokumente über Links zusam-
menhängen müssen. In diesem Fall sorgt der Dämpfungsfaktor dafür, dass tatsächlich alle
Dokumente einen PageRank Wert > 0 erhalten. Der Dämpfungsfaktor hat üblicherweise
den Wert 0.85.
Setzt man die gegebenen Variablen in die rekursive Formel 4
1−d P Rj
P Ri = +d·
X
Pn−1
n j∈Li k=0 Ck,j
ein, so erhält man für den PageRank-Wert vom i-ten LinkedDocument einen neuen PageRank-
Wert P Ri . Hierbei ist Li die Menge der Indizes der Dokumente, die einen Link aufs i-te
Dokument beinhalten. P Rj selber ist wiederum ein rekursiver Verweis auf die Formel
selbst.
4
https://de.wikipedia.org/wiki/PageRank
10
Die PageRank Werte der Dokumente werden in einem Vektor P R dargestellt und zu
Beginn auf dieselben Werte ( n1 ) gesetzt, im Beispiel ist also der PageRank Vektor P R zu
Beginn
0.25
0.25
PR = .
0.25
0.25
Aktualisiert man nun mehrfach in rekursiver Abfolge jeden Wert von PR mittels der
angegebenen Formel, so nähert sich das Ergebnis dieser Rekursion einem Vektor P R∗ an.
Dieser Vektor P R∗ entspricht den PageRank-Werten der Dokumente.
Im Beispiel entspricht dieser Ergebnisvektor
0.0547
0.0607
P R∗ = .
0.4485
0.4359
Das bedeutet dass A ein PageRank-Gewicht von 5, 47%, B von 6, 07%, C von 44, 85% und
D von 43, 56% hat.
Auf der Webseite "PageRank Explained with Javascript"5 können Sie spielerisch eine
Linkstruktur zwischen Dokumenten erstellen und die PageRank Werte der Dokumente
berechnen lassen. N.B. Ziel dieser Aufgabe ist P R∗ zu annähren bis für alle i ∈ {1, ..., n}
die folgende Bedingung erfüllt ist:
|P Ri − P Ri0 | ≤ 10−6 .
Lösungsvorschlag 8.9
Die insgesamt 6 Punkte verteilen sich wie folgt:
5
https://www2.cs.duke.edu/csed/principles/pagerank/
11
Aufgabe 8.10 (H) PageRank Iterativ (Nikolaus-Nuss) [3 Bonuspunkte]
Ziel dieser Aufgabe ist die iterative Implementierung des PageRank-Algorithmus. Dies
bedeutet, dass hier der Algorithmus entgegen seiner ursprünglichen Definition nicht re-
kursiv berechnet wird. Dies ist insofern hilfreich, als dass der rekursive Algorithmus bei
großen Dokumentzahlen zu langsam konvergiert und der hier zu implementierende itera-
tive Algorithmus im Allgemeinen effizienter ist.
1/3
A B
1/2
1/1
C 1/1
D
(a) Linkstruktur mit Gewichtung
in Erweiterung zu Abbildung 3a
Abbildung 4
Jedes Dokument verteilt gemäß Abbildung 4a sein Gewicht gleichmäßig auf alle von
ihm verlinkten Dokumente. So verweist A auf zwei Dokumente, die jeweils beide
mit 12 gewichtet werden. B verweist dagegen auf drei Dokumente, die jeweils mit 13
gewichtet werden. Allgemein gilt: Hat ein Dokument k ausgehende Links, so wird
12
jedes der k verlinkten Dokumente mit 1
k
gewichtet. Dies resultiert im Beispiel in den
Gewichtungen in Abbildung 4a.
Diese Gewichtungen bilden die Übergangsmatrix A:
A B C D
0 0 1
0 A
3
1
0 0 0 B
A= 2
1 1
0 1 C
2 3
0 3 1
1
0 D
So besagt beispielsweise die erste Spalte der Matrix, dass Dokument A jeweils mit
Gewicht 12 auf die Dokumente B und C verweist und mit Gewicht 0 (also gar nicht)
auf die Dokumente A und D. Die dritte Spalte besagt dagegen, dass Dokument C mit
Gewicht 1 auf Dokument D verweist und sonst auf keine weitere Dokumente. Eine
Person die nach dem Zufallsprinzip einem der Verweise in Dokument A folgt, wählt
demnach mit Wahrscheinlichkeit 21 entweder den Verweis zu Dokument B oder C.
Beachten Sie: Verweist ein Dokument auf kein anderes Dokument (d.h. das Do-
kument hat 0 ausgehende Links), so wird dieses Dokument so behandelt als ob es
Links zu allen anderen Dokumenten hätte.
Mit dem aus der vorhergehenden Aufgabe eingeführten Dämpfungsfaktor d berech-
net sich die PageRank Matrix M als
M =d·A+ 1−d
n
· En .
Dabei ist n die Anzahl der Dokumente und En eine Matrix mit n Zeilen und n
Spalten, die an jeder Position eine 1 enthält. Der Wert der Matrix M in Zeile i und
Spalte j, Mij berechnet sich daher als
13
Dateien zur Abgabe: Author.java, Date.java, DocumentCollectionCell.java,
DocumentCollection.java, Document.java, LinkedDocumentCollection.java,
LinkedDocument.java, Review.java, TestIt.java, WordCount.java,
WordCountsArray.java
Lösungsvorschlag 8.10
Die insgesamt 3 Punkte verteilen sich wie folgt:
14
Lösungsvorschlag 8.11
Teilaufgabe 1) 2)
Punkte 2,5 0,5
Es gibt 1 Punkte Abzug falls Relevanz richtig berechnet wird aber Dokumente nicht richtig
sortiert werden.
1. Testen Sie Ihre main-Methode ähnlich dem unten stehenden Beispiel. Führen Sie
Tests mit mindestens zwei unterschiedlichen Dokumentenstrukturen mit jeweils min-
destens fünf Dokumenten durch. Schreiben Sie ein Protokoll der Ein- und Ausgabe
Ihres Programmes als Kommentar in die Datei TestIt.java.
Beispiel: Seien die Dateien a.txt, c.txt, d.txt, e.txt wie folgt gegeben:
a.txt
es war einmal link:b.txt link:c.txt
c.txt
once upon a time link:d.txt
d.txt
erase una vez link:c.txt
e.txt
c era una volta link:b.txt
Die Ausführung der main-Methode in der Klasse TestIt sieht dann wie folgt aus:
> add b.txt:link:a.txt link:e.txt
> crawl
> pageRank
b.txt; PageRank: 0.14897680763983684
a.txt; PageRank: 0.0933151432469308
c.txt; PageRank: 0.34291508382082525
d.txt; PageRank: 0.32147782204547976
e.txt; PageRank: 0.0933151432469308
> query einmal
1. a.txt; Relevanz: 0.285917709527423
2. c.txt; Relevanz: 0.1371660335283301
3. d.txt; Relevanz: 0.1285911288181919
4. b.txt; Relevanz: 0.05959072305593474
5. e.txt; Relevanz: 0.03732605729877232
> exit
Dateien zur Abgabe: TestIt.java
15
Lösungsvorschlag 8.12
In Teilaufgabe i) sollen zwei unterschiedliche Dokumentenstrukturen mit jeweils mindes-
tens fünf Dokumenten erstellt und getestet werden. Dazu sollen Protokolle als Kommentar
in die Datei TestIt.java geschrieben werden. Für jedes solche Protokoll und die entspre-
chenden Tests gibt es 21 Punkt.
welche die Determinante einer 2×2-Matrix berechnet. Die dafür erforderliche Formel
7
lautet
a b
|A| =
= ad − bc. (1)
c d
welche die Determinante einer 3×3-Matrix nach dem folgenden Prinzip 7 berechnet:
a b c
|A| = d
e f = a
e f − b d f + c
d
e (2)
g h i h i g i g h
e f d f d e
=a −b +c (3)
h i g i g h
sowie
16
welche die übergebene Matrix matrix kopieren, die i-te Zeile bzw. Spalte von der
Kopie entfernen und ebendiese Kopie zurückgeben. Verwenden Sie diese Hilfsmetho-
den, um die Matrix wie angegeben von 3 × 3 auf 2 × 2 zu verkleinern.
Anmerkung: Die Hilfsmethoden sollen auch in der Lage sein, quadratische n × n-
Matrizen entsprechend auf (n − 1) × (n − 1) zu verkleinern.
3. Erstellen Sie die Methode detNxN(). Die Methode soll die Determinante einer be-
liebigen quadratischen n × n-Matrix berechnen. Ihr Algorithmus sollte so vorgehen,
dass die Methode detNxN() sich selbst aufruft, um die Determinante einer Subma-
trix der Größe (n − 1) × (n − 1) zu berechnen. Eine Submatrix gewinnen Sie, indem
Sie jeweils eine Zeile und eine Spalte wie vorhergehend erläutert entfernen.
Lösungsvorschlag 8.13
Punkteverteilung:
1. 0.25 Punkte
17