Update of exercises

main
Thomas Smits 2025-12-17 13:21:07 +01:00
parent 70960fe93f
commit ca65a3ac09
8 changed files with 7120 additions and 5 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
# Zusatzblatt: Textanalyse [75 Punkte]
**🎓 Benotetes Assignment 🎓**
📆 **Fällig: 06.01.2024** 📆
In einem in Kanada abgestürzten Raumschiff der außerirdischen Kryptonier wurden militärische Dokumente entdeckt, die mit einem bisher unbekannten außerirdischen Programm verschlüsselt wurden. Nun soll eine irdische Software entwickelt werden, um die Texte zu entschlüsseln und so eine mögliche Invasion der Kryptonier aufzuhalten.
Der erste Schritt zum Knacken eines Codes besteht immer darin, die Häufigkeit von Buchstaben und Worten in durchschnittlichen Texten dieser Sprache zu kennen.
Da Sie noch nicht genau wissen, ob die kryptonische Sprache auf Zeichen oder Wörtern basiert, wollen Sie sowohl die Häufigkeit von Wörtern als auch von Buchstaben analysieren. Glücklicherweise ist eine große Menge von kryptonischen Schund- und Kriegsromanen gefunden worden, sodass diese als Basis für die Analyse dienen können.
Sie bekommen daher die Aufgabe eine Software zu entwickeln, die die kryptonischen Texte auf Wort- und Buchstabenhäufigkeiten hin untersucht. Da aber Ihr Sprachkurs für kryptonisch noch nicht abgeschlossen ist, testen Sie Ihre Software vorläufig mit irdischen Texten.
Entwickeln Sie eine Software zur Analyse von Wort- und Buchstabenhäufigkeiten in beliebigen Texten. Um diese Software wiederverwendbar und modular zu halten gehen Sie bitte wie im Folgenden beschrieben vor.
**Hinweis:** Verwenden Sie die Klassen aus dem Collections-API. Hierdurch können Sie den Aufwand für diese Aufgabe drastisch reduzieren. Machen Sie keine Casts, sondern **verwenden Sie generischen Typen** korrekt und typsicher.
## TokenReader
Gehen Sie in das Paket [pr2.collections.textanalyse](../sources/src/main/java/pr2/collections/textanalyse/).
Verwenden Sie den hier angegebenen speziellen Reader (`TokenReader`), der Ihnen über die `readLineAsTokens` die Möglichkeit gibt, beliebige Texte aus einem darunterliegenden Reader zu lesen und bereits zerlegt in einzelne Wörter auszulesen. D.h. die Verwenderin der Klasse `TokenReader` muss sich keine Gedanken darüber machen, wie sie den Text in einzelne Wörter zerlegt. Dieser spezielle Reader wandelt auch bereits alle gefundenen Wörter in Kleinbuchstaben um.
## WortListe
Schreiben Sie eine Klasse `WortListe`, die die Verwaltung von Worthäufigkeiten übernimmt. Über eine Methode `add(String wort)` kann man Wörter hinzufügen. Die Klasse berechnet dann automatisch die Häufigkeiten und erlaubt es, die folgenden Informationen auszulesen:
* die absolute Häufigkeit eines bestimmten Wortes
* die relative Häufigkeit eines bestimmten Wortes
* die Anzahl aller gefundenen Wörter (d.h. inklusive Dubletten)
* die Anzahl unterschiedlicher Wörter (d.h. exklusive Dubletten)
Weiterhin soll `WortListe` es erlauben, über die gefundenen Worte mit einer `foreach`-Schleife zu iterieren, und zwar beginnend bei dem häufigsten Wort bis zum am wenigsten häufigsten Wort, d.h. die Klasse muss das Interface `Iterable` implementieren. Überlegen Sie sich, was der `Iterator` sinnvollerweise zurückgeben sollte, damit der Verwender der Klasse möglichst wenig Mühe hat.
## Buchstabenliste
Schreiben Sie analog zu der vorhergehenden Klasse eine Klasse `BuchstabenListe`, die die Verwaltung von Buchstabenhäufigkeiten übernimmt. Über eine Methode `add(String wort)` kann man Wörter hinzufügen, die in ihre Buchstaben zerlegt und analysiert werden. Die Klasse berechnet dann automatisch die Häufigkeiten der Buchstaben und erlaubt es, die folgenden Informationen auszulesen:
* die absolute Häufigkeit eines bestimmten Buchstabens
* die relative Häufigkeit eines bestimmten Buchstabens
* die Anzahl aller gefundenen Buchstaben (d.h. inklusive Dubletten)
## Textanalyse
Schreiben Sie ein Programm `Textanalyse`, das die oben beschriebenen Klassen nutzt, um beliebige Texte aus Textdateien zu analysieren. Der Name der zu analysierenden Textdatei wird auf der Kommandozeile angegeben. Das Programm lädt dann die Datei und analysiert sie entsprechend. Es gibt aus:
* den Namen der analysierten Datei
* die Anzahl der Wörter in der Datei
* die Anzahl unterschiedlicher Wörter in der Datei
* die 10 häufigsten Wörter (Rang, absolute Anzahl, prozentuale Häufigkeit und das Wort selbst)
* die Anzahl der Buchstaben in der Datei
* die 10 häufigsten Buchstaben (Rang, absolute Anzahl, prozentuale Häufigkeit und den Buchstaben selbst)
Eine Ausgabe des Werkzeugs sieht beispielsweise wie folgt aus:
```console
Analyse der Datei kafka.txt
Wörter insgesamt: 2530
Unterschiedliche Wörter: 874
Rang - Anzahl (abs) - Häufigkeit (%) - Wort
1 - 80 - 3,16% - er
2 - 66 - 2,61% - sie
3 - 64 - 2,53% - und
4 - 59 - 2,33% - die
5 - 51 - 2,02% - der
6 - 46 - 1,82% - zu
7 - 45 - 1,78% - es
8 - 41 - 1,62% - nicht
9 - 38 - 1,50% - das
10 - 35 - 1,38% - in
Zeichen insgesamt: 12683
Rang - Anzahl (abs) - Häufigkeit (%) - Wort
1 - 2179 - 17,18% - e
2 - 1316 - 10,38% - n
3 - 990 - 7,81% - i
4 - 896 - 7,06% - r
5 - 827 - 6,52% - s
6 - 721 - 5,68% - t
7 - 704 - 5,55% - a
8 - 682 - 5,38% - h
9 - 594 - 4,68% - d
10 - 423 - 3,34% - c
```
Behandeln Sie bitte auch sinnvoll den Fall, dass die angegebene Datei nicht existiert oder der Verwender vergisst, den Dateinamen anzugeben.
## TextAnalyse-Anwendung
Laden Sie sich den folgenden UTF-8 codierten Text herunter:
[Faust_I](files/faust_i.txt)
Analysieren Sie ihn mit dem oben beschriebenen Text-Analyse-Programm und geben Sie die Ausgabe als Teil Ihrer Ausarbeitung ab.

View File

@ -17,7 +17,7 @@ Die folgende Tabelle zeigt Ihnen die Themen der Woche und welche Kapitel Sie bis
| 4 | Verhaltenstherapie für Klassen | Überschreiben, Polymorphie, static, final | [4][4] | [6][ve_006], [7][ve_007], [8][ve_008], [9][ve_009], [10][ve_010], [11][ve_011], [12][ve_012] | **13.10** |
| 5 | Mit Interfaces geht es noch abstrakter | Interfaces, abstrakte Klassen, SOLID, STUPID | [5][5] | [1][ab_001], [2][ab_002], [3][in_001], [4][in_002], [5][in_003], [6][in_004] | **20.10** |
| 6 | Wer sortiert, muss trotzdem suchen | Suchen, Sortieren, Regex | [6][6] | | **27.10** |
| 7 | Geschenkverpackungen und andere Feinheiten | Object, Wrapper, Optional, Enums, Records | [7][7], [8][8] | [1][ob_001], [2][ob_002], [3][ob_003], [4][ob_004], [5][ob_005], [6][ob_006], [7][ob_007], [8][en_001], [9][en_002], [10][en_003], [11][en_004] | **03.11** |
| 7 | Geschenkverpackungen und andere Feinheiten | Object, Wrapper, Optional, Enums, Records | [7][7], [8][8] | [1][ob_001], [2][ob_002], [3][ob_003], [4][ob_004], [5][ob_005], [6][ob_006], [7][ob_007], [8][en_001], [9][en_002], [10][en_003], [11][en_004] | **03.11** |
| 8 | Wenn es mal schief geht, Ausnahmen | Exceptions, try, catch | [9][9] | [1][as_001], [2][as_002], [3][as_003], [4][as_004], [5][as_005] | **10.11** |
| 9 | Rein oder raus, die Daten müssen fließen | Input/Output mit Streams und Reader/Writer | [10][10] | [1][io_001], [2][io_002], [3][io_003], [4][io_004], [5][io_005], [6][io_006], [7][io_007], [8][io_008], [9][io_009], [10][io_010], [11][io_011], [12][io_012], [13][io_013], [14][io_014], [15][io_015], [16][io_016] | **17.11** |
| 10 | One size fits all, mit generischen Typen | Generische Typen, Wildcards | [11][11] | [1][ge_001], [2][ge_002], [3][ge_003], [4][ge_004], [5][ge_005], [6][ge_006], [7][ge_007], [8][ge_008], [9][ge_009] | **24.11** |
@ -176,6 +176,7 @@ Wichtige Einstellungen für Eclipse sind [hier](help/eclipse.md) beschrieben.
| 9. | 19.11.2025 | [Mist die Festplatte ist schon wieder voll](Assignment_009/readme.md) | **02.12.2025** |
| 10. | 03.12.2025 | [Eine Menge Mengen, bloß nicht vermengen](Assignment_010/readme.md) | **16.12.2025** |
| 11. | 03.12.2025 | [Live-Testat](Assignment_011/readme.md) | **17.12.2025** |
| 12. | 17.12.2025 | [Zusatzblatt: Textanalyse [75 Punkte]](Assignment_012/readme.md) | **06.01.2024** |
## 😀 Freiwillige Übungen
Die freiwilligen Übungen zur Vertiefung der Vorlesungsinhalte finden Sie in einem getrennten Repository: [Freiwillige Übungen](/pr2-lecture/uebungen/src/branch/master/readme.md).

View File

@ -0,0 +1,8 @@
package pr2.collections.textanalyse;
/**
* Klasse zum Verwalten von Wörtern und deren Häufigkeit.
*/
public class BuchstabenListe {
}

View File

@ -0,0 +1,13 @@
package pr2.collections.textanalyse;
/**
* Text-Analyse-Werkzeug.
*/
public class TextAnalyse {
public static void main(String[] args) {
// TODO: Methode implementieren
}
}

View File

@ -0,0 +1,51 @@
package pr2.collections.textanalyse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
/**
* Spezieller Reader, der einen Text in seine Worte zerlegt.
*/
public class TokenReader extends BufferedReader {
/**
* Erzeugt einen neune Reader.
*
* @param in der reader aus dem die Daten gelesen werden sollen.
*/
protected TokenReader(Reader in) {
super(in);
}
/**
* Liest eine Zeile aus dem Reader und gibt sie zerlegt als Wort-Tokens
* zurück. Satzzeichen werden entfernt. Wenn der Stream am Ende angekommen
* ist, wir {@literal null} zurück gegeben.
*
* @return eine Zeile der Eingabe als Wort-Tokens oder {@literal null},
* wenn das Ende des Streams erreicht wurde.
* @throws IOException IO-Problem des unterliegenden Streams.
*/
public String[] readLineAsTokens() throws IOException {
String line = readLine();
if (line == null) {
return null;
}
String[] fragments = line.split("[ .,-:?!\";()']");
List<String> token = new ArrayList<>(fragments.length);
for (String fragment : fragments) {
String f = fragment.trim();
if (!f.isEmpty()) {
token.add(f.toLowerCase());
}
}
return token.toArray(new String[0]);
}
}

View File

@ -0,0 +1,7 @@
package pr2.collections.textanalyse;
/**
* Klasse zum Verwalten von Wörtern und deren Häufigkeit.
*/
public class WortListe {
}

View File

@ -66,7 +66,7 @@ public interface Set {
* aus diesem und dem anderen Set darstellt.
*
* @param other das andere set.
* @return die Vereinigungsmenge.
* @return die Vereinigungsmenge als neues Set.
*/
Set union(Set other);
@ -84,7 +84,7 @@ public interface Set {
* behalten, die in beiden Sets vorhanden sind.
*
* @param other das andere Set.
* @return die Schnittmenge.
* @return die Schnittmenge als neues Set..
*/
Set intersection(Set other);
@ -93,14 +93,14 @@ public interface Set {
* übergebene Bedingung erfüllen.
*
* @param p Bedingung.
* @return das gefilterte Set.
* @return das gefilterte Set als neues Set.
*/
Set filter(Predicate p);
/**
* Kopiert dieses Set in das andere Set.
*
* @param other the target of the copy operation.
* @param other das Ziel der Kopieroperation.
*/
void copyInto(Set other);