Programmieren mit Harald R. Haberstroh (original) (raw)
Dienstag, 10. Oktober 2017
4. Aufgabe 4BHIF - C# Threads
Abgabename: 2017_4bhif_aufgabe4_ name_vorname.zip
Abgabetermin - 14.11.2017 - Abgabe auf edvossh
Im folgenden Code werden Primzahlen berechnet. Ihre Aufgabe ist es aus diesem Code eine Multithreaded Version zu entwickeln. Die Anzahl der Threads und der Höchstwert der Primzahlen soll über Befehlszeilenargumente einstellbar sein. Testen Sie das Programm mit verschiedenen Höchstwerten und Threadanzahlen. (Zumindestens einmal mit einer Anzahl die den Prozessoren des Systems entsprechen) Erzeugen Sie mit den Ergebnissen eine Tabelle die die Zeiten gegen die der Single-Thread-Version vergleicht. (manuell z.B. in Excel oder auch im Programm)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Diagnostics;
namespace Primzahlen { class Program { static void Main(string[] args) { Stopwatch watch = new Stopwatch(); int maxPrim = 0; int number = 0; int tests = 0; watch.Start(); Prim(1600000, out maxPrim, out number, out tests); watch.Stop(); Console.WriteLine("Es wurden {0} Primzahlen gefunden", number); Console.WriteLine("Die höchste gefundene Primzahl ist {0}", maxPrim); Console.WriteLine("Die Laufzeit betrug {0:F0} Millisekungen", watch.ElapsedMilliseconds); Console.WriteLine("Es wurden {0} Vergleiche durchgeführt", tests); }
private static void Prim(int max, out int maxPrim, out int number, out int tests)
{
List<int> prims = new List<int>();
int i = 5;
tests = 0;
prims.Add(2);
prims.Add(3);
while (i < max)
{
int maxTeiler = (int)Math.Sqrt(i) + 1;
int j = 0;
while (true)
{
int n = prims[j];
int rest = (i % n);
++tests;
if (rest == 0)
break; //keine Primzahl
if(n >= maxTeiler)
{
prims.Add(i);
break;
}
++j;
}
i += 2;
}
number = prims.Count;
maxPrim = prims[number - 1];
}
}}
Beispieltabelle für Ausgabe:
max Primzahl nr. Primzahlen ein Thread zwei Threads vier Threads 100000 9592 44ms 60ms 80ms 200000 17984 95ms 98ms 104ms 400000 33860 223ms 227ms 230ms
...
51200000 3068712 106000ms 61300ms 32940ms
Dienstag, 3. Oktober 2017
3. Aufgabe 4BHIF
Abgabename: 2017_4bhif_aufgabe3_ name_vorname.zip
Abgabetermin - 24.10.2017 - Abgabe auf edvossh
Erstellen Sie für den RPN-Rechner der letzten Aufgabe ein GUI!
Erweitern Sie die Funktionalität so, dass die Anzeige (oberstes Stack-Element C) und alternativ der gesamte Stack (CLS) gelöscht werden kann. Weiters soll ein Drop (oberstes Element entfernen), ein Swap (die beiden obersten Elemente vertauschen), ein +/- (Vorzeichenwechsel), ein 1/X, die Quadratwurzel (Sqrt) und das Quadrat (X^2) implementiert werden.

Der Rechner sollte etwa so funktionieren, wie dieser Online-Rechner.
Zusätzliche Features sind möglich und erwünscht.
Labels: .Net, 4BHIF, Aufgabe, C#
# Eingestellt von Harald R. Haberstroh @ 09:48 0 Kommentare
Sonntag, 24. September 2017
2. Aufgabe 4BHIF
Abgabename: 2017_4bhif_aufgabe2_ name_vorname.zip
Abgabetermin - 10.10.2017 - Abgabe auf edvossh
Schreiben Sie einen Stack-basierten Rechner für einen Ausdruck in umgekehrter polnischer Notation (RPN), der auch die Änderungen im Stack zeigt.
Nehmen Sie zunächst an, dass nur korrekte, durch Leerzeichen (Tabs oder Zeilenumbrüche, also White Space) getrennte, Strings von Token eines RPN-Ausdrucks übergeben werden.
Testen Sie mit dem folgenden RPN-Ausdruck:
3 4 2 * 1 5 - 2 3 ^ ^ / +Obiger Ausdruck in Infix-Notation sieht folgendermaßen aus:
3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3oder, weil ^ vor den anderen Operationen ausgewertet werden muss:
3 + 4 * 2 / ( ( 1 - 5 ) ^ 2 ^ 3 )Die Ausgabe soll so aussehen:
3 4 2 * 1 5 - 2 3 ^ ^ / +
Input Operation Stack after 3 Push [3.0] 4 Push [4.0, 3.0] 2 Push [2.0, 4.0, 3.0]
- Operate [8.0, 3.0] 1 Push [1.0, 8.0, 3.0] 5 Push [5.0, 1.0, 8.0, 3.0]
- Operate [-4.0, 8.0, 3.0] 2 Push [2.0, -4.0, 8.0, 3.0] 3 Push [3.0, 2.0, -4.0, 8.0, 3.0] ^ Operate [8.0, -4.0, 8.0, 3.0] ^ Operate [65536.0, 8.0, 3.0] / Operate [1.220703125E-4, 3.0]
- Operate [3.0001220703125] Final answer: 3.0001220703125
Hinweise:
^
bedeutet Exponent im obigen Ausdruck.
⁄
bedeutet Division.
Testen Sie den Rechner auch mit anderen Ausdrücken!
Entwurf:
Entwerfen Sie das Programm so, dass die Auswertung auch ohne die textuelle Ausgabe des Stacks erfolgt kann.
Weiters sollen auch double-Zahlen (zB -314.15927E-2) verwendet werden können.
Was passiert bei ungültigen Ausdrücken?
Erweiterung:
Wie müssten die Klassen geändert/erweitert werden, sodass man den Rechner mit so einem GUI verwenden kann?
Der Rechner sollte etwa so funktionieren, wie dieser Online-Rechner.
Bei dieser Version brauchen Sie kein GUI entwickeln, Sie sollen nur die Klassen so gestalten, dass es dann leicht ist, ein GUI dazu zu programmieren.
Labels: 4BHIF, Aufgabe, C#, POS1-4
# Eingestellt von Harald R. Haberstroh @ 21:39 0 Kommentare
Dienstag, 12. September 2017
1. Aufgabe 4BHIF
Abgabename: 2017_4bhif_aufgabe1_ name_vorname.zip
Abgabetermin - 26.9.2017 - Abgabe auf edvossh
Verwenden Sie eine Projektmappe und teilen Sie die Aufgaben in Projekte oder machen Sie ein einziges Projekt, bei dem man aber irgendwie auswählen kann, welche Teilaufgabe gestartet wird.
Sie haben nun schon zwei Jahre Java und ein Jahr Python programmiert. Nun geht es darum das bereits erworbene Können möglichst schnell auf die Sprache C# zu übertragen. Dazu sind kurze einfache Aufgabenstellungen gut geeignet. Es folgt nun eine Liste von Aufgabenstellungen für Konsolenprogramme. Sie dürfen Ihre Progrämmchen auch mit einer GUI versehen, gefordert ist das jedoch nicht.
- Hello World
Richten Sie Ihr Visual Studio so ein, dass alle Ihre Dateien automatisch einen Header mit Ihrem Namen, Klasse usw. enthalten.
Erstellen Sie dann ein "Hello World"-Programm. Dieses Programm soll "Hello World!" ausgeben, wenn keine Kommandozeilenparameter angegeben wurden, anderenfalls sollen die Parameter als Namen interpretiert werden, die dann gegrüßt werden. Dabei sollen immer zwei Namen paarweise ausgegeben werden (siehe Beispiel).
Aufruf
hello.exe Toni Barbara Klaus
Ausgabe
Hello Toni und Barbara!
Hello Klaus! - ISBN/EAN
Schreiben Sie eine Methode, welche die Prüfziffern von ISBN (Internationale Standardbuchnummer) bzw. EAN (European Article Number) prüfen kann. Dabei wird die Prüfziffer (als String) eingegeben, von welcher die Prüfziffer als Rückgabewert ausgegeben wird.
int GetCheckDigit(string isbnWithoutCheckDigit);
Daraus leitet sich eine zweite Methode ab, welche einen String inklusive Prüfziffer prüft:
bool CheckISBN(string isbn);
Diese Methode entfernt alle Trennzeichen (Leerzeichen, Bindestriche).
Algorithmus:s = z1 + z2 * 2 + z3 * 3 + ... + z9 * 9p = s mod 11- Falls p gleich 10, dann ist die Prüfziffer "X" sonst die Ziffer selbst.
Schreiben Sie analoge Methoden für EAN, ISBN-13 und EAN-13. Informationen zur Berechnung finden Sie im Internet ;-)
- Römische Zahlen
Schreiben Sie Methoden zum Umrechnen von ganzen Zahlen (1 bis 3000) in Römische Zahlen und umgekehrt. Die römischen Ziffern haben folgende Bedeutung:
I ... 1
V ... 5
X ... 10
L ... 50
C ... 100
D ... 500
M ... 1000
Beachten Sie, dass nur jeweils drei gleiche Ziffern hintereinander geschrieben werden. Stattdessen wird die nächst größere Einheit benutzt und eine Einheit abgezogen (XC = 90, XCIX = 99, IX = 9, VIII = 8).
Die Prototypen sollen sein:
string IntToRoman(int number);
int RomanToInt(string romanNumber); - Unit Tests
Erstellen Sie für die obigen beiden Aufgaben Unit-Tests. Lesen Sie dazu Verifying Code by Using Unit Tests. - Wörter suchen
Laden Sie sich die gepackte Wortliste herunter. Die Datei enthält nur eine Textdateideutsch.txt, welche eine sortierte Liste von Wörtern, jeweils ein Wort in einer Zeile enthält (stammt von Firefox). Achtung: der Zeilenumbruch besteht nur aus'\n'(Unix) und die Kodierung ist UTF-8.
Schreiben Sie eine MethodeGetWordList(string word), welche eine Liste von Worten liefert, die mit dem Stringwordbeginnen.
Implementieren Sie sowohl lineare als auch binäre Suche und vergleichen Sie diese.
Verwenden Sie unterschiedliche Datenstrukturen (die zwei Typen von C#-Arrays und Collections) und vergleichen Sie die Lösungen punkto Laufzeit und Speicherbedarf.
Schreiben Sie eine weitere MethodeGetWordListEnding(string ending), welche eine Liste von Worten liefert, die mitendingendet. Ist hier binäre Suche möglich? - Unit Tests
Erstellen sie für die obige Aufgabe passende Unit Tests. - Laufzeitmessungen
Schreiben Sie ein Programmruntime, welches die Laufzeiten der unterschiedlichen Implementierungen vonGetWordList(string word)undGetWordListEnding(string ending)ermittelt. Verwenden Sie die Wortanfänge "Distanz", "Erdbi" und "Finanzind" und die Endungen "gulierung", "dcomputer" und "chsdor".
Das Programm soll bei jedem Test folgende Informationen ausgeben:
Anzahl der gefundenen Worte und die Laufzeit.
Bilden Sie die Mittelwerte für die einzelnen Methoden (binäre/sequentielle Suche) bzw. die Implementierungen mit Arrays oder Collections.
Wie sind die Ergebnisse zu interpretieren? - 25 im Quadrat
Auf zwölf quadratischen Kärtchen sind die Zahlen 1 bis 12 gedruckt. Diese Kärtchen sollen so in einem Quadrat angeordnet werden, sodass ein 2x2-Quadrat in der Mitte frei bleibt (die Kantenlänge beträgt insgesamt also 4).- Ermitteln Sie eine Anordnung der Karten, sodass die Summe aller Karten einer Kante (4 Karten) jeweils den Wert 25 ergibt.
- Ermitteln Sie die Anzahl der Lösungen.
- Ermitteln Sie alle Lösungen (es sind sehr viele!).
Hinweis: es gibt 12! (~480.000.000) Möglichkeiten, die Kärtchen anzuordnen. Dennoch sollte es in wenigen Minuten möglich sein.
Labels: 4BHIF, Aufgabe, C#, POS1-4
# Eingestellt von Harald R. Haberstroh @ 13:47 0 Kommentare
Donnerstag, 10. März 2016
Aufgabe Regex (POS1: 2CHIF)
Schreiben Sie eine Klasse AbbreviationMatcher, welche folgendes Interface implementiert:
public interface AbbreviationMatcherInterface { public void setStrings(String[] strings); public void setSearchString(String searchstring); public String[] match(); }
Zusätzlich muss die Klasse einen Konstruktor mit zwei Parametern besitzen:
public AbbreviationMatcher(String searchstring, String[] strings) { // set the values like setSearchString() and setStrings() }
Die Methode match() liefert ein Array mit jenen Strings (aus setStrings()), auf die das Muster (ein String), welches mit setSearchString() angegeben wurde, passt.
Aus dem Suchstring (setSearchString(searchstring)) ist ein passender regulärer Ausdruck zu erzeugen. Ein String passt zum Suchstring, wenn er einfach den String "searchstring" (Groß-/Kleinschreibung ignorierend) komplett enthält oder einfach nur die Buchstaben in der gegebenen Reihenfolge beinhaltet. In diesem Fall muss der zu matchende String mit dem ersten Buchstaben beginnen.
Beispiele:Beispiele für Muster und das Ergebnis:
String "MyList"
passt auf folgende Beispielstrings:
MyList myList ThatMyList MylistMaker
String "CF"
passt auf folgende Beispielstrings:
CF ClassFinder CharacterFixer CharFinderFactory
Testen
Schreiben Sie eine (JUnit-) Testklasse AbbreviationFinderTest, welche die Methoden ausreichend testet.
Abgabe
Nennen Sie das Projekt **name_vorname_regex** und Checken Sie das Projekt am cvs.htlwrn.ac.at ein.
# Eingestellt von Harald R. Haberstroh @ 14:15 0 Kommentare
Dienstag, 19. Januar 2016
Gleitender Mittelwert (POS1: 2CHIF)
Erstellen Sie eine Klasse Averager, welche den Durchschnitt beliebig vieler Zahlen berechnen kann:
add() soll eine Zahl aufnehmengetAverage() liefert den MittelwertgetSum() liefert die Summe der ZahlengetNum() liefert die Anzahl der Zahlenreset() setzt alles zurück, d.h. ab reset() kann ein neuer Mittelwert einer Folge von Zahlen bestimmt werden.
Schreiben Sie eine passende Testklasse.
Hinweis: Dieses Beispiel kann ganz ohne Arrays gelöst werden.
Abgabe:
Nennen Sie das Projekt name_vorname_averager und Checken Sie das Projekt am `cvs.htlwrn.ac.at ein.
# Eingestellt von Harald R. Haberstroh @ 13:00 0 Kommentare
`
`` ### Dienstag, 10. November 2015
Aufgabe Java Wurzelberechnung (POS1: 2CHIF)
Man kann die Wurzel einer Zahl berechnen mit folgender Formel
xn = (xn-1 + a / xn-1) / 2
Man beginnt damit, dass a und x0 gleich der Zahl, aus der man die Wurzel ziehen will, setzt und x1 berechnet. Dann berechnet man x2 usw. bis sich die beiden letzten Werte nur mehr gering unterscheiden (z.B. die Differenz kleiner 0,0000001 ist).
Schreiben Sie eine Methode (Funktion) wurzel(zahl, genauigkeit), welche nach obigem Verfahren die Wurzel berechnet.
Erstellen Sie eine Klasse SquareRoot.java, welche eine Tabelle der Wurzeln der Zahlen 1 bis 20 bei den Genauigkeiten 0.01, 0.0001 sowie 0.0000001 ausgibt:
1: 1.0000000 1.0000000 1.0000000 2: 1.4142157 1.4142136 1.4142136 3: 1.7320508 1.7320508 1.7320508 4: 2.0000001 2.0000000 2.0000000 5: 2.2360689 2.2360680 2.2360680 6: 2.4494944 2.4494897 2.4494897 7: 2.6457670 2.6457513 2.6457513 8: 2.8284271 2.8284271 2.8284271 9: 3.0000000 3.0000000 3.0000000 10: 3.1622777 3.1622777 3.1622777 11: 3.3166248 3.3166248 3.3166248 12: 3.4641017 3.4641016 3.4641016 13: 3.6055514 3.6055513 3.6055513 14: 3.7416576 3.7416574 3.7416574 15: 3.8729837 3.8729833 3.8729833 16: 4.0000006 4.0000000 4.0000000 17: 4.1231067 4.1231056 4.1231056 18: 4.2426425 4.2426407 4.2426407 19: 4.3589018 4.3588989 4.3588989 20: 4.4721402 4.4721360 4.4721360
Stellen Sie fest, wie viele Iterationen benötigt werden. Wie kann man die Anzahl der Iterationen bestimmen, ohne die Parameter bzw. den Returntyp bzw. -wert von wurzel(zahl, genauigkeit) zu ändern?
# Eingestellt von Harald R. Haberstroh @ 10:03 0 Kommentare
Aufgaben zu Java (POS1: 2CHIF)
- Schreiben Sie ein einfaches Java Programm, welches
"Hello World"ausgibt. Nennen Sie das ProgrammHello.java. Verwenden Sie dazu einen Texteditor und übersetzen Sie das Programm auf der Kommandozeile. - Schreiben Sie ein einfaches Java-Programm, welches das kleine Einmaleins ausgibt. Welchen Namen könnte das Programm haben?
X 1 2 3 4 5 6 7 8 9 10
1 1 2 3 4 5 6 7 8 9 10
2 2 4 6 8 10 12 14 16 18 20
3 3 6 9 12 15 18 21 24 27 30
4 4 8 12 16 20 24 28 32 36 40
5 5 10 15 20 25 30 35 40 45 50
6 6 12 18 24 30 36 42 48 54 60
7 7 14 21 28 35 42 49 56 63 70
8 8 16 24 32 40 48 56 64 72 80
9 9 18 27 36 45 54 63 72 81 90
10 10 20 30 40 50 60 70 80 90 100
Verwenden Sie wieder einen Texteditor und den Java-Compiler auf der Kommandozeile.
3. Erstellen Sie mit eclipse ein Java-Projekt java-intro. Erzeugen Sie ein package intro1 ("intro eins").
Erstellen Sie in diesem Paket die beiden Klassen von oben (in das Projekt-Verzeichnis kopieren und an das package anpassen). Starten Sie die beiden Klassen von eclipse aus.
4. Starten Sie die beiden Klassen von der Kommandozeile aus. Wo sind die Class files zu finden, wie sieht der Aufruf aus?
5. Erstellen Sie im package intro1 eine Klasse Schleife, die (im main) eine Zahl einliest und dann alle Zahlen von 1 bis zu der gegebenen Zahl ausgibt. Beispielaufruf:
Grenze ? 10
1
2
3
4
5
6
7
8
9
10
6. Erweitern Sie die Klasse Schleife so, dass zwei Zahlen eingegeben werden. Es sollen dann die Zahlen von der ersten bis zur zweiten ausgegeben werden. Wenn die zweite Zahl kleiner ist, dann soll eine absteigende Folge ausgegeben werden. Beispielaufruf:
von? 15
bis? 10
15
14
13
12
11
10
# Eingestellt von Harald R. Haberstroh @ 10:00 0 Kommentare
Montag, 15. Juni 2015
Java Swing Währungsumrechner (POS1: 2BHIF)
Erstellen Sie eine Swing-GUI mit Texteingabefeldern und Labels für 5 verschiedene Währungen. Es soll ein Neu/Löschen und ein Umrechnen-Button vorhanden sein.
Wenn der Umrechnen-Button gedrückt wird, wird erkannt in welcher Währung die Eingabe erfolgte und diese Währung in alle anderen umgerechnet.
Der Neu/Löschen-Button löscht alle Eingaben.
Fehler wie z.B. keine Eingabe, Eingaben in mehreren Feldern, falsche Eingabe (Text statt Zahl) u.s.w. sollen zu keinem Programmabsturz führen sondern den Benutzer mit einem Fehlerdialog darauf hinweisen.
Das User-Interface könnte etwa so aussehen:
# Eingestellt von Harald R. Haberstroh @ 09:47 0 Kommentare
Donnerstag, 28. Mai 2015
Aufgabe JTable (POS1:3BHIF)
Erstellen Sie ein Java-Programm, welches einfache CSV-Dateien erzeugen, darstellen und ändern kann. Verwenden Sie zur Darstellung der CSV-Datei eine JTable. Beim Neuanlegen wird die Anzahl der Spalten festgelegt. Beim Laden einer CSV-Datei wird die Anzahl der Zeilen/Spalten durch die Datei gegeben. Das Programm soll es ermöglichen, jede Zelle (definiert durch Zeile und Spalte) zu ändern. Sehen Sie eine Möglichkeit zum Einfügen neuer Zeilen vor. Eine markierte Zeile soll gelöscht werden können.
Die Beschriftung der Spalten soll in der ersten Zeile der Datei gespeichert werden bzw. wird beim Laden aus der ersten Zeile der Datei entnommen.
Labels: Aufgabe, GUI, Java, POS1-3
# Eingestellt von Harald R. Haberstroh @ 13:10 0 Kommentare
Mittwoch, 20. Mai 2015
Berechnungen mit Threads parallelisieren (POS1: 3BHIF)
π kann mit Hilfe der folgenden Formel von Strömer (1986) berechnet werden:
π / 4 = 44 · arctan 1/57 + 7 · arctan 1/239 - 12 · arctan 1/682 + 24 · arctan 1/12943
Der Arcustangens wird mit der folgenden Reihenentwicklung
arctan(x) = x - x3/3 + x5/5 - x7/7 + ...
berechnet.
Folgendes Java-Programm verwendet die Klasse BigDecimal zur Berechnung von π. Es soll mittels Threads parallelisiert werden.
import java.math.; /*
@author Hans Joachim Pflug, RZ, RWTH Aachen
Berechnet PI auf eine beliebige Anzahl von Stellen genau */ public class Pi { private int dec; //Anzahl der Dezimalstellen private BigDecimal pi = new BigDecimal(0); //Ergebnis
private MathContext m; //Zur Bestimmung der Laenge der Brueche private static final BigDecimal one = new BigDecimal(1); private static final BigDecimal four = new BigDecimal(4); private BigDecimal r57; // 1/57 private BigDecimal r239; // 1/239 private BigDecimal r682; // 1/682 private BigDecimal r12943; // 1/12943/**
Erzeugt ein Objekt mit PI auf die angegebene Stellenzahl genau
@param dec Die Stellenzahl, auf die PI berechnet werden soll. */ public Pi(int dec) { this.dec = dec; m = new MathContext(dec + 5); //5 als Reserve
r57 = one.divide(new BigDecimal(57), m); r239 = one.divide(new BigDecimal(239), m); r682 = one.divide(new BigDecimal(682), m); r12943 = one.divide(new BigDecimal(12943), m);
calculate();
}
/**
- Berechnet den Wert von PI nach der Formel von Stoermer (1896):
- pi/4 = 44 * arctan(1/57) + 7 * arctan(1/239) - 12 * arctan(1/682)
+ 24 * arctan(1/12943)
*/ private void calculate() { BigDecimal sum1 = arctan(r57).multiply(new BigDecimal(44), m); BigDecimal sum2 = arctan(r239).multiply(new BigDecimal(7), m); sum1 = sum1.add(sum2, m); sum2 = arctan(r682).multiply(new BigDecimal(12), m); sum1 = sum1.subtract(sum2, m); sum2 = arctan(r12943).multiply(new BigDecimal(24), m); sum1 = sum1.add(sum2, m); pi = sum1.multiply(four, m); }
/**
Berechnet den Arcustangens einer BigDecimal-Zahl.
Benutzt die Reihe:
arctan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...
@param arg Eingabewert
@return arctan(arg) */ private BigDecimal arctan(BigDecimal arg) { BigDecimal result = new BigDecimal(0); BigDecimal z; //Abschätzung der Anzahl der Iterationen //Nach der Formel n = - d / log10(x) // n: Anzahl der Iterationen // d: Anzahl der Stellen fuer Genauigkeit // x: Argument des Arcustangens //Zwei Stellen Genauigkeit zur Sicherheit int iter = (int) -((dec + 2)/ Math.log10(arg.doubleValue()));
//Reihenentwicklung for (int i = 0; i < iter; i++) { int pow = 2 * i + 1; z = arg.pow(pow, m).divide(new BigDecimal(pow), m); if (i % 2 == 1) { z = z.negate(); } result = result.add(z, m);
} return result;
}
/**
- Gibt PI formatiert in 100er Bloecken zurueck */ public String toString() { String piS = pi.toString(); StringBuffer b = new StringBuffer(); b.append("3.1"); for (int i = 1; i < dec; i++) { if (i % 100 == 0) { b.append("\n "); } else if (i % 10 == 0) { b.append(" "); } b.append(piS.charAt(i + 2)); } return b.toString(); }
public static void main(String args[]) {
Pi p = new Pi(1000); System.out.println(p); }
}
Wieviele Threads sind hier sinnvoll?
Vergleich zwischen serieller und paralleler Berechnung:
Zeitmessungen unter Linux auf einem Intel(R) Core(TM) i3-2100 CPU @ 3.10GHz (Quadcore) (Intel(R) Core(TM) i3 CPU 560 @ 3.33GHz) mit 8GB RAM. Daneben wurden eclipse und chrome verwendet.
| Stellen | sequentiell | 4 Threads |
|---|---|---|
| 1000 | 4,395s | 2,530s |
| 2000 | 35,814s | 19,260s |
| 3000 | 126,145s | 65,693s |
| 4000 | 321,916s | 163,393s |
| 5000 | 626,394s | 323,876s |
| 6000 | 1132,480s | 568,905s |
| 7000 | 1800,781s | 912,360s |
| 8000 | 2753,654s | 1462,561s |
| 9000 | 3941,230s | 2134,741s |
| 10000 | 5527,330s | 2878,974s |
Bei der JVM kann man nicht bestimmen, ob und wie die Threads auf die CPUs (Kerne) aufgeteilt werden sollen. Die JVM und das Betriebssystem bestimmen, wie die Threads auf CPU-Kerne abgebildet werden. Das ist natürlich auch von der allgemeinen Systemlast abhängig.
Die Messungen zeigen, dass sich die Rechenzeit bei 4 Threads halbiert. Die CPU trägt zwar im Namen "Quadcore", tatsächlich ist es aber nur ein Dualcore mit vier Threads (siehe Link oben). Das bedeutet bei dieser Anwendung, dass nur zwei Threads echt parallel laufen können (weiter geteilt mit den anderen Prozessen, die auf dem System laufen).
Labels: algorithmen, Aufgabe, Java, POS1-3
# Eingestellt von Harald R. Haberstroh @ 11:54 0 Kommentare
Montag, 11. Mai 2015
Worthäufigkeiten mit binärem Baum ermitteln (POS1: 2BHIF)
Erstellen Sie ein Java-Programm welches für jedes gelesene Wort bestimmt, wie oft es vorkommt. Nach dem Ende der Eingabe (EOF) ist eine Liste von Worten und deren Häufigkeiten auszugeben.
Ein Beispiel, gegeben sei folgende Eingabe:
Das ist die erste Zeile und das ist die zweite Zeile und hier folgt die dritte Zeile. Satzzeichen gelten als Trenner. Folgendes ist kein W0rt und das 4uch nicht.
Das Programm soll dann diese Ausgabe liefern.
als 1 Das 3 die 3 dritte 1 erste 1 Folgendes 1 folgt 1 gelten 1 hier 1 ist 3 kein 1 nicht 1 Satzzeichen 1 Trenner 1 und 3 Zeile 3 zweite 1
Es erzeugt also eine Liste von Worten (in der zuerst vorkommenden Schreibweise), mit der Anzahl der Vorkommnisse.
Das Programm soll von der Standardeingabe oder von beliebig vielen Dateien lesen.
Zur Erkennung von Wörtern lesen Sie hier: Wörter in der Eingabe erkennen
Verwenden Sie dazu einen binären Baum für die Wörter.
Nennen Sie das Projekt hauf.
Labels: algorithmen, Aufgabe, Java, POS1-2
# Eingestellt von Harald R. Haberstroh @ 09:56 0 Kommentare
Aufgabe: Gruppenwechsel (POS1: 2BHIF)
Schreiben Sie eine Java-Klasse Grw.java, welches aus dem Datenbestand ski.csv die beigelegte Statistik erzeugt.
Lesen Sie die csv -Datei zeilenweise und erstellen Sie aus jeder Zeile ein Objekt einer Klasse SkiDaten, die alle notwendigen Attribute (Klasse, Name, Geb.Datum,....) enthält.
Nennen Sie das Projekt grwski.
Sollte eine neue Sortierung des Sätze notwendig sein, bitte mit OpenOffice Calc oder Excel sortieren. 1-er Kandidaten sortieren bitte mit eigenem Sortprogramm.
INFO: es handelt sich um einen zweistufigen Gruppenwechsel mit den Gruppen
KLASSE und GESCHL
und einer Gesamtdarstellung des Durchschnitts!
Eine Einführung in den Gruppenwechsel finden Sie in der Datei gruppenwechsel.pdf
Aufruf des Programms:
java Grw [-h | -o ausgabedat] [-d] eingabedatei
Die Option -d bewirkt die Ausgabe der Detailzeilen, ohne -d nur Summenzeilen ausgeben!
Beispiel Statistik:
STATISTIK zum Schuelerrennen der HTL am SKIKURS 2006 in OBERTAUERN
AMINGER Georg 0.02 ELIAS Thomas 0.97 GALAVICS Marcus 0.15 GALLAUNER Alexander 0.26 HECHER Markus 0.58 HERMANN Gregor 0.65 KAMPER Raphael 0.55 KRIVOKUCA Milan 7.73 MOSER Christoph 2.34 NEPOLA René 0.14 PRIELER Stefan 0.63 RECHBERGER Christian 3.11 RIEGLER Mario 0.87 SCHNEEBERGER Joerg 1.22 SENN Bernhard 0.65 WIESSNER Maximilian 1.61 ZENZ Markus 2.04
die durchschnittliche Zeitdifferenz bei den MAENNERN betraegt: 1.38
die KLASSE 2AHDV erreichte eine Durchschnittsdifferenz von 1.38 Sekunden
CMUND Katharina 2.81 HARATHER Alice 1.87 KONLECHNER Viktoria 0.39 RIEGER Jennifer 0.63 RINNHOFER Elisabeth 1.65 ...........................................................
........................................................... REICHHART Thomas 0.30 RIEDER Dominik 1.07 SCHERMANN Georg 0.85 STANGL Stefan 1.48 STAUFER Andreas 0.47
die durchschnittliche Zeitdifferenz bei den MAENNERN betraegt: 2.38
die KLASSE 3CHDV erreichte eine Durchschnittsdifferenz von 2.36 Sekunden ************************************************GESAMT-Differenz : 1.93
Achtung: Die obige Ausgabe stellt nur einen Ausschnitt dar (Aufruf mit Option -d) und es wurde die vorletzte Zeile (Hüpfner) gelöscht, da dort extrem abweichende Zeiten vorkommen (die Schülerin ist scheinbar gestürzt). Die Gesamt-Different würde mit dieser Zeile 11,37 Sekunden betragen.
Binäres Dateiformat für Eingabe
Erstellen Sie ein neues Programm so, dass sie statt der CSV-Eingabedatei auch eine Datei im binären Datenformat verwenden können. Die Daten sind wie folgt gespeichert (C-Datentypen):
typedef struct umsatz { char artikel[25]; char verkaeufer[25]; int vkpreis; int monat; } umsatz_t;
Dabei ist char artikel[25] ein maximal 24-Zeichen langer String, bei dem jedes Zeichen (ASCII) als ein Byte gespeichert wird. Das Ende des Strings wird durch das Zeichen '\0' abgeschlossen (das hat tatsächlich den Wert 0). D.h. es müssen bis zu 25 Bytes gelesen werden, wobei nur die Zeichen bis exklusive '\0' (direkt) in Java-chars umgewandelt werden können (verwenden Sie z.B. RandomAccessFile.read(byte[] buf)).int entspricht einem 32-Bit-Integer und passt zum Java-Typ int.
Die passende Datei mit Testdaten finden Sie hier: daten.dat.
Den Inhalt dieser Datei kann man nur mit einem Programm öffnen, das die Daten binär lesen kann und sinnvoll, z.B. im Hexadezimalsystem, anzeigen kann. khexedit oder das Konsolenprogramm hexdump eignen sich dafür.
Die Ausgabe von hexdump könnte so aussehen (gekürzt):
hp@L211 $ hexdump -C daten.dat 00000000 50 72 6f 64 30 31 00 01 4c 00 ba 01 e5 e2 e6 b7 |Prod01..L.......| 00000010 00 00 00 00 e4 98 04 08 28 4d 61 69 65 72 00 08 |........(Maier..| 00000020 a0 fc f5 b7 dc e9 b9 bf 48 e9 b9 bf f1 86 04 08 |........H.......| 00000030 90 8b f8 b7 dc 00 00 00 01 00 00 00 50 72 6f 64 |............Prod| 00000040 30 32 00 01 4c 00 ba 01 e5 e2 e6 b7 00 00 00 00 |02..L...........| 00000050 e4 98 04 08 28 4d 61 69 65 72 00 08 a0 fc f5 b7 |....(Maier......| 00000060 dc e9 b9 bf 48 e9 b9 bf f1 86 04 08 90 8b f8 b7 |....H...........| 00000070 90 01 00 00 02 00 00 00 50 72 6f 64 30 33 00 01 |........Prod03..| 00000080 4c 00 ba 01 e5 e2 e6 b7 00 00 00 00 e4 98 04 08 |L...............| 00000090 28 48 75 62 65 72 00 08 a0 fc f5 b7 dc e9 b9 bf |(Huber..........|
Es soll wieder ein 2-stufiger Gruppenwechsel programmiert werden (Artikel und Verkäufer).
Zum Vergleich können Sie die Daten auch im CSV-Format verwenden: daten.csv.
Versuchen Sie, die beiden Varianten, jene mit den Ski-Daten und jene mit den (binären) Umsatzdaten, so zu gestalten, dass nur geringe Teile unterschiedlich sind (am Besten austauschbare Klassen mit gleichem Namen für die Daten und für die Formatierung). Der Hauptalgorithmus bleibt ja gleich.
Labels: algorithmen, Aufgabe, Java, POS1-2
# Eingestellt von Harald R. Haberstroh @ 09:48 0 Kommentare
Montag, 19. Januar 2015
Worthäufigkeiten mit Collections ermitteln (POS1: 2BHIF)
Erstellen Sie ein Java-Programm welches für jedes gelesene Wort bestimmt, wie oft es vorkommt. Nach dem Ende der Eingabe (EOF) ist eine Liste von Worten und deren Häufigkeiten auszugeben.
Ein Beispiel, gegeben sei folgende Eingabe:
Das ist die erste Zeile und das ist die zweite Zeile und hier folgt die dritte Zeile. Satzzeichen gelten als Trenner. Folgendes ist kein W0rt und das 4uch nicht.
Das Programm soll dann diese Ausgabe liefern.
als 1 Das 3 die 3 dritte 1 erste 1 Folgendes 1 folgt 1 gelten 1 hier 1 ist 3 kein 1 nicht 1 Satzzeichen 1 Trenner 1 und 3 Zeile 3 zweite 1
Es erzeugt also eine Liste von Worten (in der zuerst vorkommenden Schreibweise), mit der Anzahl der Vorkommnisse. Bei der Überprüfung, ob ein Wort schon vorhanden ist, soll jedoch Groß- und Kleinschreibung nicht unterschieden werden (zum Beispiel "Und" == "und").
Das Programm soll von der Standardeingabe oder von beliebig vielen Dateien lesen.
Zur Erkennung von Wörtern lesen Sie hier: Wörter in der Eingabe erkennen
Verwenden Sie dazu eine Map für die Wörter.
Nennen Sie das Projekt hauf.
# Eingestellt von Harald R. Haberstroh @ 09:50 0 Kommentare
Sonntag, 11. Januar 2015
Aufgabe einfache Java Klassen (POS1: 2BHIF)
Erstellen Sie ein Projekt java-klassen mit zwei Klassen:
- Person
- PersonManager
nach dem folgenden Klassendiagramm:
Die Methoden der Klasse Person sollen folgende Funktionalität bereitstellen:
- Der Konstruktor
Person(String vn, String fn, int gj, char g)soll einfach die passenden Attribute setzen. print()soll Vorname, Nachname, Alter und Geschlecht auf der Konsole ausgeben.getName()liefert den Vornamen und Nachnamen mit einem Leerzeichen getrennt.getAlter(int jahr)soll das Alter in Jahren bezogen auf das im Parameter angegebene Jahr zurückliefern.toString()liefert einen String, der alle Informationen lesbar enthält.main()ist optional und enthält einfach Tests der Klasse.
Die Methoden der Klasse PersonManager sollen folgende Funktionalität bereitstellen:
print()soll einfach alle Personen ausgeben (print()vonPersonverwenden).add(Person person)nimmt eine neue Person in die interne Liste/Array auf.main()soll mindestens zwei verschiedene Personen anlegen, die dann in einen Manager aufgenommen werden. Alle Personen sollen ausgegeben werden.
Beispielaufruf auf Konsole:
hp@if205-2l $ java PersonManager Max Meier, geboren 1998 (16 Jahre alt), männlich Katrin Huber, geboren 1996 (18 Jahre alt), weiblich
# Eingestellt von Harald R. Haberstroh @ 21:12 0 Kommentare
Mittwoch, 3. Dezember 2014
Java Swing Währungsumrechner (POS1: 3BHIF)
Erstellen Sie eine Swing-GUI mit Texteingabefeldern und Labels für 5 verschiedene Währungen. Es soll ein Neu/Löschen und ein Umrechen-Button vorhanden sein.
Wenn der Umrechen-Button gedrückt wird, wird erkannt in welcher Währung die Eingabe erfolgte und diese Währung in alle anderen umgerechnet.
Der Neu/Löschen-Button löscht alle Eingaben.
Fehler wie z.B. keine Eingabe, Eingaben in mehreren Feldern, falsche Eingabe (Text statt Zahl) u.s.w. sollen zu keinem Programmabsturz führen sondern den Benutzer mit einem Fehlerdialog darauf hinweisen.
Labels: Aufgabe, GUI, Java, POS1-3
# Eingestellt von Harald R. Haberstroh @ 11:02 0 Kommentare
Montag, 1. Dezember 2014
Aufgabe Java Wurzelberechnung (POS1: 2BHIF)
Man kann die Wurzel einer Zahl berechnen mit folgender Formel
xn = (xn-1 + a / xn-1) / 2
Man beginnt damit, dass a und x0 gleich der Zahl, aus der man die Wurzel ziehen will, setzt und x1 berechnet. Dann berechnet man x2 usw. bis sich die beiden letzten Werte nur mehr gering unterscheiden (z.B. die Differenz kleiner 0,0000001 ist).
Schreiben Sie eine Methode (Funktion) wurzel(zahl, genauigkeit), welche nach obigem Verfahren die Wurzel berechnet.
Erstellen Sie eine Klasse SquareRoot.java, welche eine Tabelle der Wurzeln der Zahlen 1 bis 20 bei den Genauigkeiten 0.01, 0.0001 sowie 0.0000001 ausgibt:
1: 1.0000000 1.0000000 1.0000000 2: 1.4142157 1.4142136 1.4142136 3: 1.7320508 1.7320508 1.7320508 4: 2.0000001 2.0000000 2.0000000 5: 2.2360689 2.2360680 2.2360680 6: 2.4494944 2.4494897 2.4494897 7: 2.6457670 2.6457513 2.6457513 8: 2.8284271 2.8284271 2.8284271 9: 3.0000000 3.0000000 3.0000000 10: 3.1622777 3.1622777 3.1622777 11: 3.3166248 3.3166248 3.3166248 12: 3.4641017 3.4641016 3.4641016 13: 3.6055514 3.6055513 3.6055513 14: 3.7416576 3.7416574 3.7416574 15: 3.8729837 3.8729833 3.8729833 16: 4.0000006 4.0000000 4.0000000 17: 4.1231067 4.1231056 4.1231056 18: 4.2426425 4.2426407 4.2426407 19: 4.3589018 4.3588989 4.3588989 20: 4.4721402 4.4721360 4.4721360
Stellen Sie fest, wie viele Iterationen benötigt werden. Wie kann man die Anzahl der Iterationen bestimmen, ohne die Parameter bzw. den Returntyp bzw. -wert von wurzel(zahl, genauigkeit) zu ändern?
# Eingestellt von Harald R. Haberstroh @ 10:08 0 Kommentare
Mittwoch, 19. November 2014
Java Grafik/GUI (POS1: 3BHIF)
Einfache Grafik
Schreiben Sie eine Klasse PaintQuadrats, welche in einem Fenster (JFrame) eine Reihe von Quadraten zeichnet, die fortlaufend nummeriert sind:
Verwenden Sie eine Liste (ArrayList oder ein Feld) von Knoten (Node), die "sich zeichnen" (paint(Graphics g)) können. In der Methode paintComponents(Graphics g) des JPanels müssen dann für alle Knoten deren paint()-Methode aufgerufen werden.
Experimente mit Swing-Komponenten
Alle Steuerelemente von Swing (javax.swing.*) und AWT können auch als sogenannte Java Beans verwendet werden und damit auch dynamisch geladen werden. Eine JavaBean besitzt immer einen Standardkonstruktor. Dies ermöglicht eine standardisierte Instanzierung (vgl. Java Beans).
Im public/3bhif/java-gui-experiments/.hg finden Sie ein Mercurial Repository, welches ein Eclipse-Projekt mit den nötigen Klassen für die folgenden Beispiele enthält. Sie können in der Schule das Repository einfach klonen:
$ hg clone /home/teachers/hp/public/3bhif/java-gui-experiments Zielverzeichnis: java-gui-experiments Aktualisiere auf Zweig default 25 Dateien aktualisiert, 0 Dateien zusammengeführt, 0 Dateien entfernt, 0 Dateien ungelöst $
Damit wird im aktuellen Verzeichnis ein Projektverzeichnis java-gui-experiments erzeugt.
Das Projekt wird eventuell um neue Klassen ergänzt. Sie können sich die Änderungen holen:
$ cd java-gui-experiments $ hg pull /home/teachers/hp/public/3bhif/java-gui-experiments Hole von /home/teachers/hp/public/3bhif/java-gui-experiments Suche nach Änderungen Keine Änderungen gefunden $
Sollten Sie nicht auf einem Schul-PC das Repository klonen wollen, dann müssen Sie das Verzeichnis erst "mounten" und dann klonen:
$ mkdir ~/edvossh $ sshfs user@edvossh.htlwrn.ac.at:/home/teachers/hp/public/3bhif ~/edvossh $ hg clone ~/edvossh/java-gui-experiments Zielverzeichnis: java-gui-experiments Aktualisiere auf Zweig default 25 Dateien aktualisiert, 0 Dateien zusammengeführt, 0 Dateien entfernt, 0 Dateien ungelöst $
**user** ist natürlich mit Ihrem Usernamen in der Schule zu ersetzen. Die Eingabe des Passworts ist in obigen Beispielen nicht angezeigt,
Neue Versionen bekommen Sie sinngemäß mit hg pull ins lokale Repository.
Zurück zu den Steuerelementen/JavaBeans.
Im Projekt java-gui-experiments/bin können Sie Klassen nun aufrufen. Ein Beispiel zum Demonstrieren eines JButtons mit der Beschriftung "Hello World!" in einer 48 Punkt Schriftart:
$ cd java-gui-experiments/bin/ $ java je3.gui.ShowBean javax.swing.JButton 'text=Hello World!' font=helvetica-bold-48
Das sieht etwa folgendermaßen aus:
Sie können auch mehrere Steuerelemente auf der Kommandozeile angeben. Z.B.:
$ cd java-gui-experiments/bin/
$ java je3.gui.ShowBean javax.swing.JButton 'text=Hello World!' font=helvetica-bold-48
javax.swing.JRadioButton 'text=pick me'
java.awt.Button label=Hello javax.swing.JSlider
Experimentieren Sie mit weiteren Steuerelementen (Lesson: Getting Started with Swing).
Experimentieren Sie mit folgender Klasse. Sie zeigt die Verschachtelung verschiedener Container:
package je3.gui; import javax.swing.; import java.awt.;
/**
- A component subclass that demonstrates nested containers and components.
- It creates the hierarchy shown below, and uses different colors to
- distinguish the different nesting levels of the containers
- Containers---panel1----button1
| |---panel2----button2| | |----panel3----button3| |------panel4----button4| |----button5|---button6
*/ public class Containers extends JPanel { public Containers( ) { this.setBackground(Color.white); // This component is white this.setFont(new Font("Dialog", Font.BOLD, 24));
JPanel p1 = new JPanel( );
p1.setBackground(new Color(200, 200, 200)); // Panel1 is darker
this.add(p1); // p1 is contained by this component
p1.add(new JButton("#1")); // Button 1 is contained in p1
JPanel p2 = new JPanel( );
p2.setBackground(new Color(150, 150, 150)); // p2 is darker than p2
p1.add(p2); // p2 is contained in p1
p2.add(new JButton("#2")); // Button 2 is contained in p2
JPanel p3 = new JPanel( );
p3.setBackground(new Color(100, 100, 100)); // p3 is darker than p2
p2.add(p3); // p3 is contained in p2
p3.add(new JButton("#3")); // Button 3 is contained in p3
JPanel p4 = new JPanel( );
p4.setBackground(new Color(150, 150, 150)); // p4 is darker than p1
p1.add(p4); // p4 is contained in p1
p4.add(new JButton("#4")); // Button4 is contained in p4
p4.add(new JButton("#5")); // Button5 is also contained in p4
this.add(new JButton("#6")); // Button6 is contained in this component
}}
Starten/verwenden kann man diese Klasse mit:
$ cd java-gui-experiments/bin/ $ java je3.gui.ShowBean je3.gui.Containers
Im package je3.gui finden Sie ein paar Klassen *Layout*, welche die verschiedenen Layoutmanager demonstrieren. Dokumentation finden Sie hier: Lesson: Laying Out Components Within a Container
Ein Beispiel für das GroupLayout finden Sie in layout.Find, welches etwa so aussieht:
Verwenden Sie diese Beispiele als Basis für eigene Projekte!
Labels: Aufgabe, GUI, Java, POS1-3, User Interface
# Eingestellt von Harald R. Haberstroh @ 11:22 0 Kommentare
Montag, 10. November 2014
eclipse einrichten (POS1: 2BHIF)
Machen Sie sich mit der Entwicklungsumgebung eclipse vertraut!
- Richten Sie den "Formatter" ein, sodass nur Leerzeichen für die Einrückung verwendet werden:

- Richten Sie sich ein File-Template mit einem Header nach unseren Programmierrichtlinien ein:

- Richten Sie sich ein Code-Template mit einem Header für Klassen nach unseren Programmierrichtlinien ein:

Labels: Aufgabe, eclipse, POS1-2
# Eingestellt von Harald R. Haberstroh @ 10:17 0 Kommentare
Aufgaben zu Java (POS1: 2BHIF)
- Schreiben Sie ein einfaches Java Programm, welches
"Hello World"ausgibt. Nennen Sie das ProgrammHello.java. Verwenden Sie dazu einen Texteditor und übersetzen Sie das Programm auf der Kommandozeile. - Schreiben Sie ein einfaches Java-Programm, welches das kleine Einmaleins ausgibt. Welchen Namen könnte das Programm haben?
X 1 2 3 4 5 6 7 8 9 10
1 1 2 3 4 5 6 7 8 9 10
2 2 4 6 8 10 12 14 16 18 20
3 3 6 9 12 15 18 21 24 27 30
4 4 8 12 16 20 24 28 32 36 40
5 5 10 15 20 25 30 35 40 45 50
6 6 12 18 24 30 36 42 48 54 60
7 7 14 21 28 35 42 49 56 63 70
8 8 16 24 32 40 48 56 64 72 80
9 9 18 27 36 45 54 63 72 81 90
10 10 20 30 40 50 60 70 80 90 100
Verwenden Sie wieder einen Texteditor und den Java-Compiler auf der Kommandozeile.
3. Erstellen Sie mit eclipse ein Java-Projekt java-intro. Erzeugen Sie ein package intro1 ("intro eins").
Erstellen Sie in diesem Paket die beiden Klassen von oben (in das Projekt-Verzeichnis kopieren und an das package anpassen). Starten Sie die beiden Klassen von eclipse aus.
4. Starten Sie die beiden Klassen von der Kommandozeile aus. Wo sind die Class files zu finden, wie sieht der Aufruf aus?
5. Erstellen Sie im package intro1 eine Klasse Schleife, die (im main) eine Zahl einliest und dann alle Zahlen von 1 bis zu der gegebenen Zahl ausgibt. Beispielaufruf:
Grenze ? 10
1
2
3
4
5
6
7
8
9
10
6. Erweitern Sie die Klasse Schleife so, dass zwei Zahlen eingegeben werden. Es sollen dann die Zahlen von der ersten bis zur zweiten ausgegeben werden. Wenn die zweite Zahl kleiner ist, dann soll eine absteigende Folge ausgegeben werden. Beispielaufruf:
von? 15
bis? 10
15
14
13
12
11
10
# Eingestellt von Harald R. Haberstroh @ 09:54 0 Kommentare
Abonnieren Kommentare [Atom]
``
.png)






