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

Labels: , ,


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: , , ,


Freitag, 29. September 2017

 

vim Einführung (2AHIF, 2BHIF)

Vim ist ein hervorragender Editor mit Syntaxhervorhebung und Vergleichsfunktionen, mehreren Darstellungsfenstern und vielen anderen nützlichen Funktionen. Leider ist der Einstieg damit nicht immer ganz leicht, da vim eine Weiterentwicklung des Editors vi ist, den es bereits in den 80er Jahren gab, wo Benutzerfreundlichkeit noch eine andere Bedeutung hatte als heute. Weiterhin erscheint vim im unkonfigurierten Zustand zunächst erstmal sehr langweilig und es ist mühselig eine passende Konfiguration zu erstellen.
Der vi ist praktisch auf jedem Linux-System verfügbar und kann von der Shell (Terminal) aus verwendet werden. Daher ist es praktisch, wenn man den vi(m) beherrscht, wenn man einen Server (z.B. Web-Server) über das Internet warten muss. Die wichtigsten Funkionen kann man probieren und üben mit vimtutor
Weitere Dokumentation finden Sie hier:
vim Kurzreferenz
vim Homepage www.vim.org
vim Quick Reference Card (2 Seiten)
Wir verwenden eine spezielle Konfigurationsdatei für den vim. Im Laufe dieses Schuljahres werden wir Ihnen diese Datei (eigentlich eine überarbeitete Version, denn die bisherige Version ist hauptsächlich für C-Programmierung eingerichtet) zur Verfügung stellen. Also, bleiben Sie dran oder suchen Sie auf www.vim.org/scripts nach passenden Scripts für den vim.

vim ist eine Erweiterung des Standard-Unix-Editors vi. vim steht für vi improved.
vim gibt es nicht nur für Unix-Plattformen, sondern auch für andere Betriebssysteme (Windows, OSX). Siehe dazu auch http://www.vim.org/. vim ist frei verfügbar.
Es ist besser, einen Editor wirklich gut zu beherrschen als viele verschiedene Editoren oder Entwicklungsumgebungen nur mittelmäßig bedienen zu können. Der vim eignet sich besonders als universeller (Programmier-)Editor, da er für jede Plattform verfügbar ist und hochgradig konfigurierbar bzw. programmierbar ist.
vi gibt es auf jedem Unix-ähnlichem System. Wenn nichts mehr geht, dann muss man u.U. dem vi nehmen und in den Konfigurationsdateien Änderungen vornehmen.

vim hat (wie vi) mehrere Betriebsmodi:
Dies hat den Vorteil, dass man einen mächtigen Editor (vim ist programmierbar, arbeitet mit regulären Ausdrücken usw.) auch über einfache Terminals bedienen kann. Alle Funktionen sind über eine Standardtastatur mit Escape-Taste verfügbar. Man braucht keine Funktionstasten und keine Cursortasten. Funktions- und Cursortasten sowie Maus können bei geeigneten Terminals (X-Window System, Console) verwendet werden.
Nachteilig ist der relativ hohe Lernaufwand.

Befehlsmodus

Grundsätzlich kann jeder Befehl mehrfach ausgeführt werden, indem zuerst eine Anzahl angegeben wird. Z.B. 10dd löscht 10 Zeilen (siehe unten), 2dw löscht 2 Worte.
[Anzahl] Befehl [Taste]
[Anzahl] Befehl [Bereich]
Cursorbewegung
k hinauf
h l links rechts
j hinunter
^F orward page
^B ackward page
^D own half page
^U p half page
w ord right
b ack word
[line]G oto line (default letzte Zeile)
( Sätze zurück
) Sätze vorwärts
{ Absätze zurück
} Absätze vorwärts
fc gehe zum Zeichen c in der aktuellen Zeile
'm gehe zu Marke m
ma mark a (setze Marke a), Marken werden auch für Lösch-, Änder- und Kopieroperationen verwendet (sieh weiter unten)
Löschen (d elete)
dd Zeile löschen
dw Wort löschen
x Zeichen unter Cursor löschen
X Zeichen links von Cursor löschen
D bis Zeilenende löschen
Bereichd löschen des Bereichs
d'marke löschen bis zur Marke marke (ein Buchstabe, vorher gesetzt mit mmarke)
Ändern
> schiebt Text nach rechts (shiftwidth)
< schiebt Text nach links (shiftwidth)
i Einfügen vor Cursor (insert)
a Einfügen nach Cursor (append)
I Einfügen Zeilenanfang (Insert)
A Einfügen Zeilenende (Append)
o Öffnet neue Zeile darunter (open line)
O Öffnet neue Zeile darüber
J (join) hänge die nächste Zeile an die aktuelle Zeile an (mit Leerzeichen getrennt)
rx ersetzen des aktuellen Zeichens durch das Zeichen x (kein ESC nötig)
cw ändert Wort (change word)
Bereichc ändert Bereich (vgl. Bereich angeben)
c'marke ändert Bereich bis zur Marke
Bereich angeben (markieren)
Cursor an ein Ende des Bereichs setzen, v eingeben, den Cursor zum anderen Ende bewegen und den gewünschten Befehl eingeben. Zeilenweise markieren mit V.
Wurde :set mouse=a gesetzt, dann kann auch mit der Maus markiert werden.
Fast alle Befehle arbeiten mit einem so markierten Bereich.
Kopieren/Einfügen
Bereichy "yank", Bereich wird in den Puffer kopiert
y'marke kopiert Bereich bis zur Marke in den Puffer
yw Wort in den Puffer
Y Zeile in den Puffer
p Einfügen nach Cursor (paste - "einkleben")
Suchen
^A sucht nächstes Vorkommen des Wortes unter Cursor
% platziert Curser auf zugehörige ( ) { } [ ]
Anzahl% platziert Cursor auf Anzahl Prozent der Datei
/text sucht vorwärts text oder regulären Ausdruck
?text sucht rückwärts text oder regulären Ausdruck
* sucht das Wort unter dem Cursor
Wiederholung
. (Punkt) wiederholt letztes Kommando
n letzte Suche wiederholen
N letzte Suche in umgekehrter Richtung
Rückgängig
u undo, der vi kann nur die letzte Änderung rückgängig machen (d.h. uu stellt die letzte Änderung wieder her), der vim kann im Prinzip beliebig viele Änderungen rückgängig machen
^r (crtl+r) redo (nur vim) macht das letzte undo bzw. die letzten undos wieder rückgängig
Sonstige Kommandos
^G zeigt Dateistatus und Zeilennummer
^L erneuert Bildschirm
Bereich! führt angegebenen Bereich einem Filter zu, der anschließend eingegeben werden muss

Änderungsmodus

Eingegebener Text wird eingefügt (bei i, a,...) bzw. ersetzt markierten Bereich (c,...), löschen mit Backspace in der aktuellen Zeile möglich (nur eben eingegebener Text).
Der Änderungsmodus wird mit der ESC-Taste verlassen.
^v (ctrl+v) stellt sicher, dass das nächste Zeichen normal eingegeben wird (z.B. wird bei TAB normalerweise nicht das Tabulator-Zeichen eingefügt sondern so viele Leerzeichen als nötig, will man jedoch das TAB-Zeichen einfügen, muss man ^vTAB drücken).

Ex-Befehle (Colon mode)

:[Zeile][,Zeile]Befehl Argumente
Der Bereich Zeile,Zeile bezeichnet Anfangszeile und Endzeile. Ein . (Punkt) bedeutet aktuelle Zeile, $ die letzte Zeile. Wurde vorher ein Bereich mit v ausgewählt, dann wird automatisch ein Bereich eingefügt: '<,'> (die Marke '< bezeichnet den Anfang und '> das Ende eines markierten Bereichs). % ist die Kurzform von 1,$.
:x Speichern und Ende
:w write, speichern
:w datei Speichern in Datei (write), wurde vorher ein Bereich markiert, so wird dieser Bereich in die datei geschrieben.
:r datei Einfügen von Datei (read)
:q Quit (schließen eines Fensters)
:split [datei] weiteres Fenster (mit datei öffnen)
Suchen und ersetzen
:s/suchtext/ersatztext/[g]
Ersetzen von suchtext durch ersatztext. Wird g (die eckigen Klammern bezeichnen "optional") angegeben, dann wird auch mehrfaches Vorkommen pro Zeile ersetzt. suchtext kann ein regulärer Ausdruck sein.
Wenn kein Bereich angegeben wird, dann wird die Ersetzung nur in der aktuellen zeile durchgeführt. Wird ein Bereich markiert, so wird nur in diesem Bereich ersetzt. Es können auch Zeilennummern angegeben werden:
:.,$s/i++/j++/g ersetze alle i++ durch j++ von der aktuellen Zeile bis zum
Ende der Datei.
Setzen von Modi
:se tabstop=3 Tabulatorweite
:se shiftwidth=3 Weite für > und <
:se ai oder :set autoindent automatisches Einrücken
:se et oder :set expandtab Tabulator wird durch Leerzeichen ersetzt (dies sollte eingestellt werden!)
:syntax on Highlighting von Sourcen
Abkürzungen
:ab lhs rhs Definieren einer Abkürzung lhs (left hand side) für rhs (right hand side), Abkürzungen werden expandiert, sobald ESC, Enter oder die Leertaste gedrückt wird.
:ab listet alle Abkürzungen auf.
:unab lhs löscht die Abkürzung lhs.
:help abbreviate Hilfe zu den Abkürzungen.
Konfigurationsdatei .vimrc
In dieser Datei können beliebige Ex-Befehle stehen. Diese Datei wird beim Starten von vim ausgeführt. Weitere Konfigurationsmöglichkeiten sind in der Dokumentation (:help) beschrieben. So können Abkürzungen definiert werden, Funktionstasten belegt werden und in Abhängigkeit eines Dateityps Konfigurationsdateien ausgeführt werden.
reguläre Ausdrücke
Reguläre Ausdrücke werden immer wieder benötigt. Der vim erlaubt es reguläre Ausdrücke zu beim Suchen. Das Programm grep erlaubt reguläre Ausdrücke. Reguläre Ausdrücke ermöglichen es Suchmuster anzugeben. Dabei gibt es viel mehr Möglichkeiten als bei den Shell-Suchmustern. Es folgen beispielhaft die wichtigsten Ausdrücke:
\. (Punkt) steht für ein beliebiges Zeichen
[aeiou] ein Selbstlaut klein geschrieben
[A-Z] alle Großbuchstaben
[^0-9] alles außer Ziffern
cdrom\|floppy alle Vorkommnisse der Worte cdrom oder floppy
a\+ mindestens ein a (a, aa, aaa, aaaa, ...)
.* keines, ein oder mehrere beliebige Zeichen (der * braucht
keinen
\)
\(ausdruck\)+ das Muster ausdruck muss mindestens einmal
vorkommen
ausdruck{von,bis} ausdruck muss mindestens von mal und höchstens
bis mal vorkommen.
ausdruck{n} ausdruck muss genau n mal vorkommen.
^ausdruck ausdruck muss am Zeilenanfang stehen.
Ausdruck$ ausdruck muss am Zeilenende stehen.
Die Operatoren \+ und * sind "gefräßig", d.h. sie nehmen soviel als möglich, u.U. bis zum Ende eine Zeile. Der Ausdruck a.*h passt auf ah, ahh, abh, abhcdh.
Beispiele:
[0-9A-Fa-f]+ erkennt Hexadezimalzahlen, z.B. 123, abc, F000 usw.
\(un\)*stable erkennt stable, unstable, ununstable,
unununstable etc.
\(un\)\{-,1}stable erkennt stable und unstable
int [a-z]\+(.*); passt auf alle Prototypen von int-Funktionen, die nur
Kleinbuchstaben im Namen haben.

Tipps

Wenn man nicht weiß, in welchem Modus sich der vi bzw. vim gerade befindet, drückt man am besten die ESC-Taste, dann ist man sicher im Befehlsmodus.
Generell ist zu empfehlen, :help tutor zu machen.
Mit :version erhält man Informationen zur Variable $VIM .
Der vi bzw. vim speichert regelmäßig gemachte Änderungen in eine Datei, die mit . (Punkt) beginnt und mit .swp (oder .swb, .swc usw.) endet. Dazwischen befindet sich der Name der editierten Datei (Aufruf vim hello.c, Sicherungsdatei .hello.swp). Beim Speichern und Beenden wird diese Datei gelöscht. Wird der vi bzw. vim gewaltsam terminiert (Stromausfall, killall -KILL vim, schließen des Terminals, in dem der vim läuft o.ä.), dann wird diese Sicherungsdatei nicht gelöscht. Darin sind im Allgemeinen fast alle Änderungen gespeichert.
Wird nach dem "Absturz" der vim wieder mit der vorigen Datei gestartet, so gibt er die Information aus, dass es eben diese Sicherungsdatei gibt und wie man die letzten Änderungen wiederherstellt. Das funktioniert normalerweise mit vim -r datei (-r wie recover). Wenn man dann alles geprüft hat, dann speichert man die Datei. Danach muss man die Sicherungsdatei löschen, da sonst wieder beim Starten von vim die Information angezeigt wird.
vim ist ein konfigurierbarer Editor, er hat eine eigene Programmiersprache eingebaut. Es gibt für viele Aufgaben fertige Scripts im Internet (http://www.vim.org ist ein guter Einstiegspunkt). Solche Scripts werden automatisch geladen, wenn sie sich im Verzeichnis ~/.vim/plugin befinden.

Labels: ,


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 ^ 3
oder, 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: , , ,


Dienstag, 12. September 2017

 

Automatische Header in C# (Visual Studio)

Eine Einfache Möglichkeit einen Header in jede Source-Datei eines Projekts einzufügen, ist die Verwendung des Plugins License Header Manager. Dort findet sich auch ein Hinweis zur Verwendung.

Labels: , , ,


 

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.

  1. 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!
    
  2. 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:
    1. s = z1 + z2 * 2 + z3 * 3 + ... + z9 * 9
    2. p = s mod 11
    3. 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 ;-)
  3. 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);
    
  4. Unit Tests
    Erstellen Sie für die obigen beiden Aufgaben Unit-Tests. Lesen Sie dazu Verifying Code by Using Unit Tests.
  5. Wörter suchen
    Laden Sie sich die gepackte Wortliste herunter. Die Datei enthält nur eine Textdatei deutsch.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 Methode GetWordList(string word), welche eine Liste von Worten liefert, die mit dem String word beginnen.
    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 Methode GetWordListEnding(string ending), welche eine Liste von Worten liefert, die mit ending endet. Ist hier binäre Suche möglich?
  6. Unit Tests
    Erstellen sie für die obige Aufgabe passende Unit Tests.
  7. Laufzeitmessungen
    Schreiben Sie ein Programm runtime, welches die Laufzeiten der unterschiedlichen Implementierungen von GetWordList(string word) und GetWordListEnding(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?
  8. 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).
    1. Ermitteln Sie eine Anordnung der Karten, sodass die Summe aller Karten einer Kante (4 Karten) jeweils den Wert 25 ergibt.
    2. Ermitteln Sie die Anzahl der Lösungen.
    3. 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: , , ,


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.

Labels: , ,


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 aufnehmen
getAverage() liefert den Mittelwert
getSum() liefert die Summe der Zahlen
getNum() liefert die Anzahl der Zahlen
reset() 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.

Labels: , ,


Montag, 23. November 2015

 

OOP in Java, Beispiel Geld/Währungstabelle (POS1: 2CHIF)

Laut Wikipedia kann Objektorientierte Programmierung definiert werden als:

Die objektorientierte Programmierung (kurz OOP) ist ein auf dem Konzept der Objektorientierung basierendes Programmierparadigma. Die Grundidee besteht darin, die Architektur einer Software an den Grundstrukturen desjenigen Bereichs der Wirklichkeit auszurichten, der die gegebene Anwendung betrifft. Ein Modell dieser Strukturen wird in der Entwurfsphase aufgestellt. Es enthält Informationen über die auftretenden Objekte und deren Abstraktionen, ihre Typen. Die Umsetzung dieser Denkweise erfordert die Einführung verschiedener Konzepte, insbesondere Klassen, Vererbung, Polymorphie und spätes Binden.

Alan Kay, der Erfinder der Programmiersprache Smalltalk und des Begriffs „object oriented“, definierte ihn im Kontext von Smalltalk folgendermaßen:

1. Everything is an object, 2. Objects communicate by sending and receiving messages (in terms of objects), 3. Objects have their own memory (in terms of objects), 4. Every object is an instance of a class (which must be an object), 5. The class holds the shared behavior for its instances (in the form of objects in a program list), 6. To eval a program list, control is passed to the first object and the remainder is treated as its message

„1. Alles ist ein Objekt, 2. Objekte kommunizieren durch das Senden und Empfangen von Nachrichten (welche aus Objekten bestehen), 3. Objekte haben ihren eigenen Speicher (strukturiert als Objekte), 4. Jedes Objekt ist Instanz einer Klasse (welche ein Objekt sein muss), 5. Die Klasse beinhaltet das Verhalten aller ihrer Instanzen (in der Form von Objekten in einer Programmliste), 6. Um eine Programmliste auszuführen, wird die Ausführungskontrolle dem ersten Objekt gegeben und das Verbleibende als dessen Nachricht behandelt“
– Alan Kay: The Early History of Smalltalk (1993)

Beispielanwendung

Anhand des folgenden Beispiels soll ein kurzer Einblick in die Objektorientierte Programmierung gegeben werden.

Es soll Geld implementiert werden. Da es in verschiedenen Ländern unterschiedliche Währungen gibt, muss unsere Klasse neben dem Betrag auch die Währung beinhalten. Um rechnen zu können wird noch eine Währungstabelle mitgespeichert.

Die Währungstabelle wechselkurs könnte natürlich auch wieder in eigenen Klassen/Objekten realisiert werden (im Java-Code ist das auch tatsächlich der Fall).

Die Attribute (Eigenschaften) sind alle öffentlich (public), da damit das Beispiel kürzer wird. Tatsächlich werden normalerweise die Attribute nach außen unsichtbar gemacht (private) und nur Methoden (Methoden-Aufrufe entsprechen Alan Kays "Nachrichten") öffentlich gemacht, um den Zugriff auf das Innere der Objekte zu verhinden (Information Hiding oder Datenkapselung).

Die Methode getEuro() liefert den auf Euro umgerechneten Geldbetrag.
Die Methode add(geld) addiert den Wert des Parameters geld zum Wert des aktuellen Objekts und erzeugt ein neues Objekt mit der Summe und liefert es als Returnwert zurück.

Der Konstruktor wird in diesem Klassendiagramm nicht angegeben. Durch ihn wird aber die Währung der Betrag festgelegt. Der Konstruktor wird ausgeführt, wenn ein Objekt erzeugt wird.

Die Umsetzung in Java:

In Java heißt die Referenz auf das aktuelle Objekt this. this wird nicht als Parameter deklariert (anders als in Python). Den Methoden fehlt ein this-Parameter (bzw. self in Python). Dieser Parameter existiert nur intern.
Dennoch kann man this beim Zugriff auf Attribute (und Methoden) angeben. Im folgenden Beispiel wird das auch gemacht.

Man muss this nur dann angeben, wenn es sonst zu Mehrdeutigkeiten käme (in unserem Beispiel beim Konstruktor, bi dem die Parameter genauso benannt sind wie die Attribute).

Der Kunstruktor heißt in Java immer so wie die Klasse, in unserem Fall Geld().

Die Währungstabelle wechselkurs wird als Array einer eigenen Klasse Wechselkurs realisiert. Zusätzlich benötigt man mangels Dictionary eine Methode, die zu einer gegebenen Währung den Kurs liefert: getKurs()

class Geld {
    final class Wechselkurs { // final nur für's scrapbook
        String waehrung;
        double kurs;

        public Wechselkurs(String waehrung, double kurs) {
            this.waehrung = waehrung;
            this.kurs = kurs;
        }
    }

    private Wechselkurs[] wechselkurs = { 
        new Wechselkurs("USD", 1.505),  // US-$ (1EUR sind 
                                        // 1.505 USD)
        new Wechselkurs("GBP", 0.908),  // Britische Pfund
        new Wechselkurs("EUR", 1.0),  
        new Wechselkurs("CHF", 1.509),  // Schweizer Franken
        new Wechselkurs("JPY", 130.582),// Japanische Yen
    };

    String waehrung;
    double betrag;

    public Geld(String waehrung, double betrag) {
       this.waehrung = waehrung;
       this.betrag = betrag;
    }

    public double getEuro() {
       return this.betrag / this.getKurs();
    }

    private double getKurs() {
        for (Wechselkurs kurs : this.wechselkurs) {
            if (kurs.waehrung.equals(this.waehrung)) {
                return kurs.kurs;
            }
        }
        return 0.0;
    }

    public Geld add(Geld geld) {
        double summeInEuro = this.getEuro() + geld.getEuro();
        Geld summe = new Geld(this.waehrung, 
                              summeInEuro * this.getKurs());
        return summe;
    }
}

/*** Testaufrufe ***/
Geld hotelrechnung = new Geld("EUR", 560);
Geld mietwagen = new Geld("USD", 760);
Geld summe = mietwagen.add(hotelrechnung);
System.out.printf("Summe: %s%.2f, %s%.2f\n", summe.waehrung, 
    summe.betrag, "EUR", summe.getEuro());

Testausgabe:

Summe: USD1602,80, EUR1064,98

Scrapbook oop.jpage zum Download.

Labels: , ,


 

Java Arrays

Folgendes Beispiel zeigt ein zweidimensionales Array, bei dem die zweite Dimension für jede Zeile unterschiedlich lang ist. In der Animation ist sichtbar, wie dieses Array von Arrays im Speicher organisiert ist.

hier finden Sie die Animation direkt am Python-Tutor.

Labels: ,


Dienstag, 17. November 2015

 

Java-for Schleife wie in Python

Python arbeitet mit Sequenzen. Manchmal ist es praktisch, wenn man eine Sequenz direkt bei der for-Schleife hin schreiben kann. Ein Beispiel:
for i in [1, 3, 2, 5, 10, -3]:
    print(i, end=" ")
print()
In Java ist das ganz ähnlich möglich. Hier ein zwei Varianten:
class T {
    // helper method
    public static int[] list(int... values) {
        return values;
    }
    public static void main(String[] args) {
        // use helper to generate array
        for (int i : list(1, 3, 2, 5, 10, -3)) {
            System.out.printf("%d ", i);
        }
        System.out.println();

        // use locally defined array
        for (int i : new int[] { 1, 3, 2, 5, 10, -3 }) {
            System.out.printf("%d ", i);
        }
        System.out.println();
    }
}
Die Ausgabe sind dann die Zahlen in der Liste:
1 3 2 5 10 -3 
1 3 2 5 10 -3 

Die Hilfsmethode helper() nützt das Java-Feature der variablen Parameterliste, die dann in eine Sequenz (Array) umgewandelt wird.

Die zweite Variante verwendet die Initialisierung von Arrays.

Auch mit beliebigen Objekten ist das Prinzip machbar:

for o in [1, "a", 23.3, "hallo", 3]:
    print(o, end=" ")
print()
public class ListsInForLoop {
    // helper
    public static Object[] olist(Object... objects) {
        return objects;
    }

    public static void main(String[] args) {
        // different kinds of Objects
        for (Object o : olist(1, "a", 23.3, "hallo", 3)) {
            System.out.print(o);
            System.out.print(" ");
        }
        System.out.println();

        // use locally defined Object array
        for (Object o : new Object[] { 1, "a", 23.3, "hallo", 3 }) {
            System.out.print(o);
            System.out.print(" ");
        }
        System.out.println();
    }

}
Die Ausgabe ist dann so:
1 a 23.3 hallo 3 
1 a 23.3 hallo 3

Labels:


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?

Labels: , ,


 

Aufgaben zu Java (POS1: 2CHIF)


  1. Schreiben Sie ein einfaches Java Programm, welches "Hello World" ausgibt. Nennen Sie das Programm Hello.java. Verwenden Sie dazu einen Texteditor und übersetzen Sie das Programm auf der Kommandozeile.
  2. 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
    

Labels: , ,


 

eclipse einrichten (POS1: 2CHIF)

Machen Sie sich mit der Entwicklungsumgebung eclipse vertraut!
  1. Richten Sie den "Formatter" ein, sodass nur Leerzeichen für die Einrückung verwendet werden:
  2. Richten Sie sich ein File-Template mit einem Header nach unseren Programmierrichtlinien ein:
  3. Richten Sie sich ein Code-Template mit einem Header für Klassen nach unseren Programmierrichtlinien ein:

Labels: ,


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:

Labels: , ,


This page is powered by Blogger. Isn't yours?

Abonnieren Posts [Atom]