Sonntag, 30. September 2012

 

Abgaben (POS1: 2BHIF, 3BHIF)

Bis es ein zentrales Repository für Abgaben gibt, gilt folgende Form der Abgabe:
  1. Erzeugen Sie ein Mercurial-Repository (hg init).
  2. Arbeiten Sie an der Lösung der Aufgabe und nehmen Sie die neuen Dateien in Ihr Repository auf (hg add).
  3. Übergeben Sie einen fertigen Arbeitsschritt an das Repository (hg commit).
  4. Sind alle Teilaufgaben gelöst bzw. der Abgabetermin erreicht, packen Sie das Repository in ein Archiv mit dem Namen jjjj_Nbhif_aufgabeN_name_vorname.tgz
  5. Kopieren Sie dieses Archiv in das Abgabeverzeichnis /home/teachers/hp/abgabe/Nbhif/.

Dabei bedeuten:
jjjj
Die Jahreszahl des Schuljahresbeginns. Für das Schuljahr 2012/13 also 2012.
N
Bei der Klasse, der Jahrgang (also 2bhif, 3bhif) und bei der Aufgabe die Aufgabennummer (aufgabe1, aufgabe2...).
name_vorname
Ihr Name und Vorname in Kleinbuchstaben sowie ohne Umlaute, scharfes s (ß) und Akzente.

Beispiel:
2012_3bhif_aufgabe2_mayer_juergen.tgz
Dieses Archiv sollte in das Verzeichnis
/home/teachers/hp/abgabe/3bhif/
kopiert werden.

Bei jeder Aufgabe steht nun zur Erinnerung ganz oben der Abgabename. Zum Beispiel:
Abgabename: 2012_3bhif_aufgabe2_name_vorname.tgz

Erstellen Sie auch für die bereits per Mail abgegebenen Aufgaben Repositories, packen Sie diese in ein entsprechendes Archiv und geben Sie es wie oben beschrieben ab!

Labels: , , ,


Dienstag, 25. September 2012

 

Aufgabe Regex (POS1: 3BHIF)

Abgabename: 2012_3bhif_aufgabe2_Name_Vorname.tgz

ClassFinder

Erstellen Sie ein Projekt class_finder und erzeugen Sie ein Mercurial Repository dafür.

Schreiben Sie eine Java-Klasse MyClassFinder, welche folgendes Interface implementiert (Header wurde weggelassen):
package classfinder;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.LinkedList;

public interface ClassFinder {
 /**
  * finds Classes using the Pattern.
  * 
  * The pattern could be a simple String, i.e. "MyList" which matches all
  * classnames (java-filenames) containing "MyList" (i.e. "ThatMyList",
  * "Mylist", "MylistMaker",...) ignoring case, or it is a pattern like "SCM"
  * (all capital letters) which means names like "SimulateComputerModel",
  * "SCM", "StrCatMaker" and so on.
  * 
  * @param pattern
  * @return List of filenames
  * @throws FileNotFoundException
  * @throws IOException
  */
 public LinkedList<String> findClassFiles(String pattern)
   throws FileNotFoundException, IOException;

 /**
  * finds files containing methods using the Pattern.
  * 
  * The pattern could be a simple String, i.e. "doThis" which matches all
  * classnames (filenames) containing method declarations "doThis" ignoring
  * case, or it is a pattern like "scm" (ignore case) which means methods
  * like "searchClassMembers", "scM", "strCatMerger" and so on. So pattern
  * should be interpreted in both ways.
  * 
  * @param pattern
  * @return List of filenames
  * @throws FileNotFoundException
  * @throws IOException
  */
 public LinkedList<String> findMethodFiles(String pattern)
   throws FileNotFoundException, IOException;
}

Ihre Klasse darf im Prinzip einen beliebigen Namen haben, nur nicht classfinder.ClassFinder, denn das ist der Name des Interfaces, welches implementiert werden muss (in einem anderen Paket, darf die Klasse natürlich gleich heißen).

Die Idee der Methode findClassFiles(String pattern) ist es, das Aktuelle Verzeichnis und die Unterverzeichnisse nach Klassen (Java-Dateien) zu durchsuchen, die dem gegebenen Muster entsprechen.

Beispiele für Muster und das Ergebnis:
MyList
liefert folgende Dateien:
MyList.java
myList.java
ThatMyList.java
MylistMaker.java
    
CF
liefert folgende Dateien:
CF.java
ClassFinder.java
CharacterFixer.java
CharFinderFactory.java
    
Die Methode findMethodFiles(String pattern) liefert die Klassennamen (ohne .java), welche die gesuchten Methodendeklarationen enthalten. Eine Methode passt, wenn der Name einfach den String pattern (Groß-/Kleinschreibung ignorierend) enthält oder einfach nur die Buchstaben in der gegebenen Reihenfolge enthält. In diesem Fall muss der Methodenname mit dem ersten Buchstaben beginnen.

Beispiele für Muster und die passenden Methoden:
doThis
passt zu folgenden Methodennamen:
doThis
dothis
tryToDoThis
doTaskHelpings
    
ScM
passt zu folgenden Methodennamen:
scm
doScm
searchClassMembers
setCornerMarker
    
Natürlich müssen aber die dazugehörigen Klassennamen geliefert werden, ggf. mit package (z.B. classfinder.MyClassFinder).

Testen

Schreiben Sie eine (JUnit-) Testklasse ClassFinderTest, welche die Methoden ausreichend testet.

Main

Schreiben Sie eine Hauptklasse Finder, welche ein passendes Konsoleninterface zu ClassFinder bietet:
hh@knuth:~$ java Finder -c MyList
MyList.java
myList.java
ThatMyList.java
maker/MylistMaker.java
hh@knuth:~$ java Finder -m ScM
MyClass
helpers.Helper
gui.Main
gui.Frame
hh@knuth:~$ java Finder -h
Finder, a java-tool for finding classes and methods.
(c) 2012, Harald R. Haberstroh
hh@knuth:~$
Die Hervorhebung der passenden Zeichen ist optional. Die Hilfe sollte natürlich etwas ausführlicher sein und muss Ihren Namen enthalten.

Hinweise

Labels: , , ,


Montag, 24. September 2012

 

Mini-Vergleich verschiedener Programmiersprachen

Dieser Artikel vergleicht ein paar Programmiersprachen (die in der Abteilung Informatik der HTL Wiener Neustadt unterrichtet werden) und dient nur zur Demonstration der "Optik" dieser Sprachen.

Als Beispiel kommt "99 bottles of beer" zum Einsatz. Die Programme stammen von http://99-bottles-of-beer.net/ und dienen eigentlich nur als Beispiele, um die Code-Struktur kleinerer Programme zu sehen.

Python

Python unterstützt mehrere Programmierparadigmen. So werden objektorientierte, aspektorientierte und funktionale Programmierung unterstützt. Wie andere dynamische Sprachen wird Python oft als Skriptsprache genutzt.
"""
99 bottles of beer in Python
"""
for quant in range(99, 0, -1):
    if quant > 1:
        print(quant, "bottles of beer on the wall,", quant, "bottles of beer.")
        if quant > 2:
            suffix = str(quant - 1) + " bottles of beer on the wall."
        else:
            suffix = "1 bottle of beer on the wall."
    elif quant == 1:
        print("1 bottle of beer on the wall, 1 bottle of beer.")
        suffix = "no more beer on the wall!"
    print("Take one down, pass it around,", suffix)
    print("--")
Hier die Python Lösung zum Ausführen

Java

Java ist eine objektorientierte Programmiersprache und eine eingetragene Marke des Unternehmens Sun Microsystems (seit 2010 Oracle). Die Programmiersprache ist ein Bestandteil der Java-Technologie – diese besteht grundsätzlich aus dem Java-Entwicklungswerkzeug (JDK) zum Erstellen von Java-Programmen und der Java-Laufzeitumgebung (JRE) zu deren Ausführung. Die Laufzeitumgebung besteht selbst aus der virtuellen Maschine (JVM) sowie den mitgelieferten Bibliotheken der Java-Laufzeitumgebung.
/*
 * 99 bottles of beer in Java
 */
class bottles {
    public static void main(String args[]) {
        String s = "s";
        for (int beers=99; beers>-1;) {
            System.out.print(beers + " bottle" + s + " of beer on the wall, ");
            System.out.println(beers + " bottle" + s + " of beer, ");
            if (beers==0) {
                System.out.print("Go to the store, buy some more, ");
                System.out.println("99 bottles of beer on the wall.\n");
                System.exit(0);
            } else
                System.out.print("Take one down, pass it around, ");
            s = (--beers == 1)?"":"s";
            System.out.println(beers + " bottle" + s + " of beer on the wall.\n");
        }
    }
}

C

C ist eine imperative Programmiersprache, die der Informatiker Dennis Ritchie in den frühen 1970er Jahren an den Bell Laboratories für die Systemprogrammierung des Betriebssystems Unix entwickelte. Seitdem ist sie auf vielen Computersystemen verbreitet. Die Anwendungsbereiche von C sind sehr verschieden. Sie wird zur System- und Anwendungsprogrammierung eingesetzt. Die grundlegenden Programme aller Unix-Systeme und die Systemkerne vieler Betriebssysteme sind in C programmiert. Zahlreiche Sprachen, wie C++, Objective-C, C#, Java, PHP, Vala oder Perl orientieren sich an der Syntax und anderen Eigenschaften von C.
/* 
 * 99 bottles of beer in C
 */
#define MAXBEER (99)

void chug(int beers);

main()
{
    register beers;

    for(beers = MAXBEER; beers; chug(beers--))
        puts("");

    puts("\nTime to buy more beer!\n");

    exit(0);
}

void chug(register beers)
{
    char howmany[8], *s;

    s = beers != 1 ? "s" : "";
    printf("%d bottle%s of beer on the wall,\n", beers, s);
    printf("%d bottle%s of beeeeer . . . ,\n", beers, s);
    printf("Take one down, pass it around,\n");

    if(--beers) sprintf(howmany, "%d", beers); else strcpy(howmany, "No more");
    s = beers != 1 ? "s" : "";
    printf("%s bottle%s of beer on the wall.\n", howmany, s);
}

C++

C++ ist eine von der ISO genormte Programmiersprache. Sie wurde ab 1979 von Bjarne Stroustrup bei AT&T als Erweiterung der Programmiersprache C entwickelt. C++ ermöglicht sowohl die effiziente und maschinennahe Programmierung als auch eine Programmierung auf hohem Abstraktionsniveau.

C++ unterstützt mehrere Programmierparadigmen:
/*
 * 99 bottles of beer in C++
 */
#include <iostream>
using namespace std;

int main()
{
    int bottles = 99;
    while ( bottles > 0 )
    {
        cout << bottles << " bottle(s) of beer on the wall," << endl;
        cout << bottles << " bottle(s) of beer." << endl;
        cout << "Take one down, pass it around," << endl;
        cout << --bottles << " bottle(s) of beer on the wall." << endl;
    }
    return 0;
}

C#

C# (lies englisch c sharp, englische Aussprache [ˌsiːˈʃɑːp]) ist eine vom Softwarehersteller Microsoft im Rahmen seiner .NET-Strategie entwickelte Programmiersprache. C# ist bei ECMA und ISO als Standard registriert.

C# unterstützt mehrere Programmierparadigmen:
/*
 * 99 bottles of beer in C#
 */
using System;
using System.Linq;
using System.Text;

namespace NinetyNineBottles
{
  class Beer
  {
    static void Main(string[] args)
    {
        StringBuilder beerLyric = new StringBuilder();
        string nl = System.Environment.NewLine;

        var beers =
            (from n in Enumerable.Range(0, 100)
             select new { 
               Say =  n == 0 ? "No more bottles" : 
                     (n == 1 ? "1 bottle" : n.ToString() + " bottles"),
               Next = n == 1 ? "no more bottles" : 
                     (n == 0 ? "99 bottles" : 
                     (n == 2 ? "1 bottle" : n.ToString() + " bottles")),
               Action = n == 0 ? "Go to the store and buy some more" : 
                                 "Take one down and pass it around"
             }).Reverse();

        foreach (var beer in beers)
        {
            beerLyric.AppendFormat("{0} of beer on the wall, {1} of beer.{2}",
                                    beer.Say, beer.Say.ToLower(), nl);
            beerLyric.AppendFormat("{0}, {1} of beer on the wall.{2}", 
                                    beer.Action, beer.Next, nl);
            beerLyric.AppendLine();
        }
        Console.WriteLine(beerLyric.ToString());
        Console.ReadLine();
    }
  }
}

Labels: , , , ,


Sonntag, 23. September 2012

 

Denksport mit Python, erste Anwendung von Mercurial (POS1: 2BHIF)

Abgabename: 2012_2bhif_aufgabe2_Name_Vorname.tgz

Lesen Sie Mercurial Einführung und legen Sie
  1. die Datei ~/.hgrc nach dem Muster des obigen Artikels an:
    [ui]
    username = Vorname Name <i99999@student.htlwrn.ac.at>
    
  2. ein Projekt mit dem Namen brain_teasers an.
  3. ein Mercurial Repository an.
Arbeiten Sie die Aufgaben der Reihe nach ab und nehmen Sie das jeweilige Pythonscript in das Repository auf. Machen Sie (spätestens) dann ein commit, wenn das Programm funktioniert (oder wenn es zumindest ohne Syntaxfehler läuft).

Schreiben Sie folgende Pythonprogramme:
pythagorean_triple.py
Es soll ein Pythagoreisches Tripel (a2 + b2 = c2 für a < b < c) für a + b + c == 1000.
sumdigits2pow1000.py
Es soll die Ziffernsumme (Quersumme, engl. cross sum) der Zahl 21000 ermittelt werden. Die Zahl soll als Programmargument angegeben werden.
sumdigitsfact.py
Es soll die Ziffernsumme der Fakultät von 100 (100!) ermittelt werden. Die Zahl soll als Programmargument angegeben werden.
palindrome4.py
Generiere 4-stellige Palindrome als Produkt 2-steliger Zahlen. Die Faktoren und das Palindrom soll ausgegeben werden. Da die Multiplikation kommutativ ist, müssen Duplikate entfernt werden: 74x66 == 66x74 (4884), also nur einmal ausgeben.
palindrome6.py
Generiere 6-stellige Palindrome als Produkt 3-steliger Zahlen. Gib das Maximum der Palindrome aus.

Labels: , ,


 

Python Kommandozeilenparameter

Kommandozeile (unter Linux/Unix)

Gleich zur Kommandozeilenbearbeitung mit Python
Folgender Artikel gibt einen kurzen Einblick in die Geschichte der Kommandozeile: Commandline resurrected.

Viele Aufgaben lassen sich auch wesentlich schneller auf der Kommandozeile erledigen als mit der grafischen Oberfläche (Click-Click-Drag usw). Ein paar Beispiele (Shell bedeutet hier Kommandozeile):

Suche alle .c Dateien, die neuer sind als Makefile.


Shell... find . -name ' *.c' -newer Makefile -print
GUI... Öffne den Explorer, navigiere zum entsprechenden Verzeichnis, Klicke auf die Datei Makefile und merke das Änderungsdatum bzw. Zeit. Dann Starte Tools/Find und gib *.c als Suchkriterium ein. Wähle den Datumsreiter und gib das gemerkte Datum ein. Klicke OK.

Erzeuge an zip/tar-Archiv meines Sourcecodes (C-Code).


Shell... zip archive.zip *.h *.c oder tar cvf archive.tar *.h *.c
GUI... Öffne ein ZIP-Werkzeug (z.B. WinZip), wähle "Neues Archiv", gib den Namen ein, wähle das (Quell-)Verzeichnis im Hinzufügen Dialog, setze den Filter auf *.c und klicke "Hinzufügen", dann setze einen weiteren Filter auf *.h und klicke "Hinzufügen" und schließe das Archiv wieder.

Ein letztes Beispiel:

Welche Java-Dateien wurden letzte Woche geändert?


Shell... find . -name '*.java' -mtime +7 -print
GUI... Klicke und navigiere zu "Suche Dateien", klicke auf "Name" und gib "*.java" ein, wähle "Datum letzte Änderung" und klicke auf "Beginndatum", gib das Startdatum des Projekts ein (wann war das, verd**** noch mal?). Weiters klicke auf "Endedatum" und gib das Datum von vor einer Woche ein (schau mal schnell auf einen Kalender...). Klicke "Suche".
Anmerkung: Möglicherweise sind die genauen Bezeichnungen bzw. Beschriftungen beim GUI nicht ganz korrekt, denn die hängen von der Version sowie von Typ der Grafischen Oberfläche (GUI = Graphical User Interface) ab. Die (Shell-) Befehle sind jedoch korrekt.

Befehls-Syntax

Unix (Linux) Befehle haben folgende einheitliche Struktur. Bis auf den Befehlsnamen (Programmname) sind grundsätzlich alle anderen Angaben optional.
Befehlsname [Option...] [Argument...] [Ein-/Ausgabeumlenkung]
Die eckigen Klammern deuten an, dass dieser Parameter optional ist. Die drei Punkte geben zusätzlich an, dass mehrere solcher Parameter möglich sind.
Optionen sind syntaktisch von anderen Argumenten unterscheidbar: sie beginnen mit einem Minus, haben einen Buchstaben und danach optional ein Argument für diese Option
-x [Argument]
oder sie beginnen mit zwei Minus und einem Optionsnamen sowie dem optionalen Argument.
--Optionsname [Argument]

Befehlsargumente sind Dateinamen oder andere für den Befehl wichtige Informationen.
Normalerweise lesen Unix-Programme Eingaben vom Terminal und geben Ausgaben auf das Terminal aus. Diese Datenkanäle können durch Ein-Ausgabeumlenkung geändert werden. Diese Umleitungen unterscheiden sich ebenfalls von den Optionen und anderen Argumenten (< Eingabedatei, > Ausgabedatei und | für die Pipe).
<
Das Kommando liest von der angegebenen Datei (statt von der Tastatur).
>
Das Kommando schreibt in die angegebene Datei (statt auf das Terminal).
|
Die Ausgabe des Kommandos links vom | wird als Eingabe für das Kommando rechts vom | verwendet. Die Kommandos sind über eine Pipe (Leitung, Rohrleitung) verbunden.
Ein paar Beispiele:
hh@knuth:~$ cd workspace
hh@knuth:~/workspace$ ls
c2bf  demo  eclimd.log  guidemo  libbf  programmierblog  python  python3  python-sum
pythontest  pythonX  scm-demo  _SCRIPTS_  unit-tests
hh@knuth:~/workspace$ cd c2bf
hh@knuth:~/workspace/c2bf$ ls
1tox  cc  GPL  ld  Makefile  math  README  strip  test.sh  wrapper
hh@knuth:~/workspace/c2bf$ cd cc
hh@knuth:~/workspace/c2bf/cc$ ls
ast.h  c2bf-cc  c2bf-dispast  dispast.c  dispast.o  genbf  genbf.h  genbfmain.c
genbfmain.o  gram.o  gram.y  main.c  main.o  Makefile  README.txt  scan.l  
scan.o  tests  y.output  y.tab.h
hh@knuth:~/workspace/c2bf/cc$ ls *.c *.h
ast.h  dispast.c  genbf.h  genbfmain.c  main.c  y.tab.h
hh@knuth:~/workspace/c2bf/cc$ ls -l *.c *.h
-rw-rw-r-- 1 hh hh 21061 Aug 31 21:40 ast.h
-rw-rw-r-- 1 hh hh 30503 Aug 31 21:40 dispast.c
-rw-rw-r-- 1 hh hh  6627 Aug 31 21:40 genbf.h
-rw-rw-r-- 1 hh hh   953 Aug 31 21:40 genbfmain.c
-rw-rw-r-- 1 hh hh   917 Aug 31 21:40 main.c
-rw-rw-r-- 1 hh hh  7631 Aug 31 21:45 y.tab.h
hh@knuth:~/workspace/c2bf/cc$ cd
hh@knuth:~$
Mehr Informationen zur Shell (Kommandozeile) gibt es hier: Bash (Shell)

Kommandozeilenparameter mit Python bearbeiten

Das (Standard-) Modul sys ermöglicht es von Python auf die Umgebung, in der Python läuft, zuzugreifen. In unserem Fall wenden wir uns der Kommandozeile zu.
#!/usr/bin/python3
import sys

print("commandline:")
for arg in sys.argv:
    print(arg)
hh@knuth:/tmp$ vim cmd.py 
hh@knuth:/tmp$ cat cmd.py 
#!/usr/bin/python3
import sys

print("commandline:")
for arg in sys.argv:
    print(arg)
hh@knuth:/tmp$ python3 cmd.py -o --option par1 par2
commandline:
cmd.py
-o
--option
par1
par2
hh@knuth:/tmp$ chmod +x cmd.py 
hh@knuth:/tmp$ ./cmd.py -o --option par1 par2
commandline:
./cmd.py
-o
--option
par1
par2
hh@knuth:/tmp$ 
Die Zeile
#!/usr/bin/python3
dient dazu, dem Betriebssystem zu sagen, mit welchem Programm diese (Text-) Datei zu starten ist, wenn man sie mit chmod +x file ausführbar gemacht hat.

Sie sehen, dass alle Parameter nach python3 ausgegeben werden. Ist die Pythondatei ausführbar, bekommt man die (fast) dieselbe Ausgabe (./ vor einem Kommando bedeutet, dass dieses Kommando im aktuellen Verzeichnis und nicht im Pfad zu finden ist).
hh@knuth:/tmp$ python3
Python 3.2.3 (default, Sep 10 2012, 18:14:40) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> type(sys.argv)
<class 'list'>
>>> 
sys.argv ist eine Liste, die alle Kommandozeilenparameter inklusive des Scriptnamens enthält. Das Pythonprogramm muss die Argumente entsprechend behandeln: Optionen erkennen, Argumente verwenden. Nur die Ein-/Ausgabeumlenkung braucht man nicht im Programm behandeln (solange man nur die Standardkanäle verwendet).
hh@knuth:/tmp$ ./cmd.py -o --option par1 par2 > outputfile
hh@knuth:/tmp$ cat outputfile
commandline:
./cmd.py
-o
--option
par1
par2
hh@knuth:/tmp$ 
Bei der Ausgabeumleitung auf die Datei outfile "verschwindet" die Ausgabe in dieser Datei.

Ein einfaches Beispiel, das den "Typ" der Argumente ausgibt:
import sys

def info(progname):
    """print some information"""
    print(str.format("""
usage:
    {0} [-h] [parameter...]
prints type of parameters

Options:
-h ... this help

(c) 2012 Harald R. Haberstroh
    """, progname))
    
    
if __name__ == '__main__':
    if "-h" in sys.argv:
        info(sys.argv[0])
    else:
        for arg in sys.argv:
            if arg.isdigit():
                print("number", arg)
            elif arg.isalpha():
                print("word", arg)
            else:
                print("string", arg)
hh@knuth:/tmp$ python3 cmdline.py 123 Harald '+$' -h

usage:
    cmdline.py [-h] [parameter...]
prints type of parameters

Options:
-h ... this help
    
(c) 2012 Harald R. Haberstroh
hh@knuth:/tmp$ python3 cmdline.py 123 Harald '+$' 
string cmdline.py
number 123
word Harald
string +$
hh@knuth:/tmp$
Ihre Python-Programme sollten immer eine Hilfe mit der Option -h oder --help anbieten. Dort muss auch Ihr Name und die Klasse ausgegeben werden.

Nach der Ausgabe der Hilfe (Info) soll das Programm beendet werden. Damit kann man wie im obigen Beispiel einfach -h an die Kommandozeile anhängen.

In der Hilfe/Info muss auch immer der Programmname wie im Beispiel ausgegeben werden (sys.argv[0])!

Labels: , ,


Dienstag, 18. September 2012

 

Mercurial Einführung

Mercurial ist ein Version Control System (abk. VCS, dt. Versionsverwaltungssystem). Software-Entwickler verwenden es um ihren Source Code zu verwalten. Zweck von Mercurial ist:
  1. Verwalten (und Speichern) aller alten Versionen von jeder Datei
  2. Verschiedene Versionen des Source Codes zusammenführen, sodass Team-Mitglieder unabhängig voneinander am Code arbeiten können um dann ihre Änderungen wieder zusammenzuführen.
Ohne Versionsverwaltung müsste man die verschiedenen Versionen in Verzeichnissen mit unterschiedlichen Namen speichern:
hh@knuth:~/Dokumente/mercurial-demo$ ls -l
insgesamt 20
drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 Copy (2) of CountDown
drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 Copy (3) of CountDown
drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 Copy of CountDown
drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 CountDown
drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 CountDown 2012-09-18
Das ist mühsam und verwirrend und benötigt eine Menge Speicherplatz (das Projekt ist dann praktisch vollständig in jeder Kopie des Projektverzeichnisses). Mit einem VCS kann man das viel besser machen.

Die meisten arbeiten mit Mercurial auf der Kommandozeile. Das funktioniert völlig identisch unter Linux, Windows und Mac. Das Kommando ist hg:
hh@knuth:~/Dokumente/mercurial-demo$ hg
Mercurial Distributed SCM

Grundlegende Befehle:

 add        Fügt die angegebenen Dateien der nächsten Version hinzu
 annotate   Zeigt Informationen über Änderungssätze pro Dateizeile an
 clone      Erzeugt eine Kopie eines bestehenden Projektarchivs
 commit     Übernimmt Änderungen der angegebenen Dateien oder alle
            ausstehenden Änderungen ins Archiv
 diff       Zeigt Änderungen des Projektarchivs oder angegebener Dateien an
 export     Gibt Kopfzeilen und Änderungsverlauf einer oder mehrerer Versionen
            aus
 forget     Angegebene Dateien ab dem nächsten Commit nicht mehr unter
            Versionskontrolle stellen
 init       Erzeugt ein neues Projektarchiv im angegebenen Verzeichnis
 log        Zeigt die Revisionshistorie des Archivs oder von Dateien an
 merge      Führt das Arbeitsverzeichnis mit einer anderen Revision zusammen
 pull       Holt Änderungen aus dem angegebenen Projektarchiv
 push       Überträgt lokale Änderungen in das angegebene Ziel
 remove     Entfernt die angegebenen Dateien in der nächsten Version
 serve      Startet einen eigenständigen Webserver
 status     Zeigt geänderte Dateien im Arbeitsverzeichnis
 summary    Fasst den Status des Arbeitsverzeichnisses zusammen
 update     Aktualisiert das Arbeitsverzeichnis (oder wechselt die Version)

Nutze "hg help" für eine Liste aller Befehle oder "hg -v" für Details
Vielfach ist das Betriebssystem auf englisch eingestellt:
hh@knuth:~/Dokumente/mercurial-demo$ hg
Mercurial Distributed SCM
                                
basic commands:
                                
add        add the specified files on the next commit
annotate   show changeset information by line for each file
clone      make a copy of an existing repository
commit     commit the specified files or all outstanding changes
diff       diff repository (or selected files)
export     dump the header and diffs for one or more changesets
forget     forget the specified files on the next commit
init       create a new repository in the given directory
log        show revision history of entire repository or files
merge      merge working directory with another revision
pull       pull changes from the specified source
push       push changes to the specified destination
remove     remove the specified files on the next commit
serve      export the repository via HTTP
status     show changed files in the working directory
summary    summarize working directory state
update     update working directory
                                
use "hg help" for the full list of commands or "hg -v" for details
Im weiteren werden Sie nur mehr die englischen Ausgaben sehen!

Um Mercurial verwenden zu können, muss noch eine Konfigurationsdatei .hgrc im Homeverzeichnis angelegt werden:
hh@knuth:~ $ cat > .hgrc
[ui]
username = Name <user@email.com>
<Strg-D>
hh@knuth:~ $
Name und E-Mail muss natürlich sinnvoll sein (z.B. Manfred Bauer <mbauer10922@gmail.com>). Die Datei kann natürlich mit jedem Texteditor angelegt werden.

Um eine Versonsverwaltung zu verwenden, benötigt man ein Repository (dt Lager, Magazin). Das Repository speichert alle alten Versionen aller Dateien eines Verzeichnisses. Natürlich wird ein platzsparendes Verfahren verwendet. Es werden die Dateien plus aller Änderungen gespeichert.

Früher war das Anlegen eines Repositories ziemlich mühsam. Mit Mercurial geht das ganz einfach: einfach ins Hauptverzeichnis des Projekts (des Dateibaums) wechseln und hg init eingeben.
hh@knuth:~/Dokumente/mercurial-demo$ cd c2bf
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ ls -a
.  ..  .project  1tox  GPL  Makefile  README  cc  ld  math  strip  test.sh  wrapper
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg init
hh@knuth:~/Dokumente/mercurial-demo/c2bf$
Was ist nun passiert? Ein Verzeichnis .hg wurde angelegt:
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ ls -a
.  ..  .hg  .project  1tox  GPL  Makefile  README  cc  ld  math  strip  test.sh  wrapper
.hg ist das Repository. Ein Verzeichnis mit allem Drum und Dran für Mercurial. Einstellungen, alte Versionen von Dateien, Tags (dt Etiketten, Marken), ein paar extra Socken, wenn es kalt wird usw. In dem Verzeichnis hat man nichts verloren, man sollte da nicht händisch herumdrehen, da könnte was kaputt gehen.

Das Repository ist noch leer. Die Dateien müssen noch hinzugefügt werden.
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg add
adding .project
adding 1tox/BF1to2.txt
adding 1tox/BF1to4.txt
adding 1tox/Makefile
adding 1tox/MultiBitwidth.txt
adding 1tox/c2bf-1to16bit
adding 1tox/c2bf-1to2
adding 1tox/c2bf-1to2.c
adding 1tox/c2bf-1to2.o
adding 1tox/c2bf-1to32bit
adding 1tox/c2bf-1to4
adding 1tox/c2bf-1to4.c
adding 1tox/c2bf-1to4.o
adding GPL
adding Makefile
adding README
adding cc/Makefile
adding cc/README.txt

uswusf...viele Dateien...

hh@knuth:~/Dokumente/mercurial-demo/c2bf$
Ein Schritt fehlt noch... die Änderungen müssen committed (commit - übergeben) werden. Welche Änderungen?

Das Hinzufügen der neuen Dateien.

Commit sagt Mecurial, dass der aktuelle Dateibestand als neue Version übernommen werden soll. Solange kein commit erfolgt, wird im Repository nichts geändert.
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg commit
Mercurial öffnet nun einen Editor (bei mir vim), sodass eine Nachricht eingegeben werden kann. Diese Nachricht ist eine Erinnerung für den Programmierer, die beschreiben soll, was sich geändert hat.
Initial version of the c2bf code.

HG: Enter commit message.  Lines beginning with 'HG:' are removed.
HG: Leave message empty to abort commit.
HG: --
HG: user: hh 
HG: branch 'default'
HG: added .project
HG: added 1tox/BF1to2.txt
HG: added 1tox/BF1to4.txt
HG: added 1tox/Makefile
HG: added 1tox/MultiBitwidth.txt
HG: added 1tox/c2bf-1to16bit
HG: added 1tox/c2bf-1to2
HG: added 1tox/c2bf-1to2.c
HG: added 1tox/c2bf-1to2.o
HG: added 1tox/c2bf-1to32bit
HG: added 1tox/c2bf-1to4
HG: added 1tox/c2bf-1to4.c
HG: added 1tox/c2bf-1to4.o
HG: added GPL
HG: added Makefile
HG: added README
HG: added cc/Makefile
HG: added cc/README.txt
HG: added cc/ast.h
HG: added cc/c2bf-cc
HG: added cc/c2bf-dispast
"/tmp/hg-editor-eMVxZ3.txt" 204L, 6635C 
Im vim muss man zuerst I (großes i) dann gleich den Text eingeben. Mit <Esc> (Esc-Taste) und :x<enter> (Eingabetaste) speichern.

Mit hg log bekommt man eine Liste der Änderungen.
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg log
changeset:   0:3d54225035a3
tag:         tip
user:        hh 
date:        Tue Sep 18 21:00:02 2012 +0200
summary:     Initial version of the c2bf code.

Jetzt ändern wir eine Datei:
So, nun Übergeben wir die Änderung an Mercurial: hg commit
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg commit
Mercurial erkennt die Änderung und bietet wieder den Editor für die Commit-Nachricht an:
Added comment.

HG: Enter commit message.  Lines beginning with 'HG:' are removed.
HG: Leave message empty to abort commit.
HG: --
HG: user: hh 
HG: branch 'default'
HG: changed test.sh
~                                                                                                                                                                                                                                             
~                                                                                                                                                                                                                                             
~                                                                                                                                                                                                                                             
~                                                                                                                                                                                                                                             
~                                                                                                                                                                                                                                             
hg log zeigt nun folgendes an:
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg log
changeset:   1:ad33e88c004f
tag:         tip
user:        hh 
date:        Tue Sep 18 21:24:58 2012 +0200
summary:     Added comment.

changeset:   0:3d54225035a3
user:        hh 
date:        Tue Sep 18 21:00:02 2012 +0200
summary:     Initial version of the c2bf code.
hg log funktioniert wie ein Blog: das Neuseste wird zuoberst angezeigt.

Werden versehentlich Dateien gelöscht oder nicht funktionierende Änderungen im Sourcecode gemacht, kann man mit hg revert --all die Änderungen bis zum letzten Commit zurücknehmen.

--all nimmt alle Änderungen aller Dateien zurück.

Statt --all kann eine Liste von Dateien angegeben werden, für die man die Änderungen zurücknehmen will.
Wenn Sie mit Mercurial an einem Projekt arbeiten, dann sollten Sie folgendermaßen vorgehen:
  1. Mache ein paar Änderungen
  2. Schau, ob sie funktionieren
  3. Funktionieren sie, dann hg commit
  4. Andernfalls hg revert --all
  5. GOTO 1
Will man wissen, welche Dateien sich geändert haben, kann man hg status verwenden:
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ ls
1tox  GPL  Makefile  README  cc  ld  math  strip  test.sh  wrapper
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ vim test.sh
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ cp test.sh testall.sh
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ rm GPL
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg status
M test.sh
! GPL
? testall.sh
M bedeutet modified, also geändert. ! bedeutet fehlend, die Datei war beim letzten Commit noch da, ist aber nun verschwunden. ? bedeutet unbekannt, Mercurial weiß von dieser Datei (noch) nichts.

Will man nun wissen, was sich in einer Datei geändert hat, kann man hg diff verwenden:
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg diff test.sh 
diff -r ad33e88c004f test.sh
--- a/test.sh Tue Sep 18 21:24:58 2012 +0200
+++ b/test.sh Tue Sep 18 21:54:11 2012 +0200
@@ -1,5 +1,6 @@
 #!/bin/bash
 # run tests with c2bf
+#
 BFI=egobfi16
 
 # Test 1
Das ist etwas kryptisch, aber oft verwendet man eine IDE, welche die Änderungen schön anzeigt. mit gvim und ein paar Shell-Tricks bekommt man das auch hin.
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg cat test.sh | \
gvim - -c  ":vert diffsplit test.sh" -c 'map q :qa!<CR>'

Damit die Änderungen von oben committed werden können, müssen noch das ! und ? behandelt werden. Dass die Datei GPL gelöscht wurde, muss mit hg remove gekanntgegeben werden und die neue Datei testall.sh muss mit hg add Mercurial bekannt gemacht werden:
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg status
M test.sh
! GPL
? testall.sh
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg remove GPL 
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg st
M test.sh
R GPL
? testall.sh
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg add
adding testall.sh
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg st
M test.sh
A testall.sh
R GPL
A bedeutet nun added (hinzugefügt) und R removed (gelöscht).

Die Änderungen werden aber erst mit hg commit ins Repository übernommen!

Übrigens kann man die hg-Kommandos abkürzen, wie man beim letzten Beispiel sieht. Man benötigt nur so viele Zeichen bis das Kommando eindeutig ist.

Nach dem Commit, sieht das Log so aus:
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg com
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg log
changeset:   2:a8ff7f27bcaf
tag:         tip
user:        hh 
date:        Tue Sep 18 22:24:30 2012 +0200
summary:     some major changes.

changeset:   1:ad33e88c004f
user:        hh 
date:        Tue Sep 18 21:24:58 2012 +0200
summary:     Added comment.

changeset:   0:3d54225035a3
user:        hh 
date:        Tue Sep 18 21:00:02 2012 +0200
summary:     Initial version of the c2bf code.

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg status
hh@knuth:~/Dokumente/mercurial-demo/c2bf$
Beim Log zeigt changeset die Versionsnummern an. Die Versionsnummern bestehen aus zwei Teilen, einer "lesbaren" Zahl wir 0 (initiale Version) oder 1 sowie nach dem : eine komische Hexadezimalzahl, welche meist "ignoriert" werden kann.

Wie man sieht, zeigt nun hg status nichts mehr an, alle Änderungen wurden übernommen.

Mit hg cat kann man sich jede beliebige Version einer Datei aus dem Repository anzeigen lassen. Mit der Option -r [zahl] (-r wie revision) kann man sich die Version mit der Nummer [zahl] anzeigen lassen.
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg cat test.sh 
#!/bin/bash
# run tests with c2bf
#
BFI=egobfi16

# Test 1

uswusf...viele Zeilen...

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg cat -r 0 test.sh 
#!/bin/bash
BFI=egobfi16

# Test 1

uswusf...viele Zeilen...

Übrigens kann die Option -r [zahl] auch bei hg diff verwendet werden:
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg diff -r 0 test.sh 
diff -r 3d54225035a3 test.sh
--- a/test.sh Tue Sep 18 21:00:02 2012 +0200
+++ b/test.sh Tue Sep 18 22:41:20 2012 +0200
@@ -1,4 +1,6 @@
 #!/bin/bash
+# run tests with c2bf
+#
 BFI=egobfi16
 
 # Test 1
Mit hg update kann man den Inhalt des aktuellen Verzeichnisses auf jede beliebige Version setzen. hg update -r 279999 liefert leider keine super coole SciFi Version mit Laserschwertern unseres Projekts. Jede Version in der Vergangenheit ist aber möglich. Ohne Versionsnummer wird die aktuelle Version (tip) verwendet.
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg update -r 0
2 files updated, 0 files merged, 1 files removed, 0 files unresolved
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ head -6 test.sh
#!/bin/bash
BFI=egobfi16

# Test 1
echo -n "Test  1: "
./wrapper/c2bf cc/tests/test1.c
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg up -r 1
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ head -6 test.sh
#!/bin/bash
# run tests with c2bf
BFI=egobfi16

# Test 1
echo -n "Test  1: "
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg up
2 files updated, 0 files merged, 1 files removed, 0 files unresolved
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ head -6 test.sh
#!/bin/bash
# run tests with c2bf
#
BFI=egobfi16

# Test 1
hh@knuth:~/Dokumente/mercurial-demo/c2bf$ 
Übrigens zeigt das Kommando head die mit -[zahl] angegeben Anzahl von Zeilen an (in unserem Beispiel immer 6). Das Kommando hat wie auch vim nichts mit Mercurial zu tun.

In einem weiteren Artikel werde ich zeigen, wie man zusätzlich ein zentrales Repository für ein Team (oder für Abgaben :-)) verwenden kann.
In Zukunft sollten Sie folgendermaßen an Ihren Aufgaben arbeiten:
  1. Bearbeite einen Punkt der Aufgabe (Mache ein paar Änderungen)
  2. Schau, ob sie funktionieren
  3. Funktionieren sie, dann hg commit
  4. Andernfalls hg revert --all
  5. GOTO 1
Abgegeben wird dann das Repository, also das Verzeichnis .hg, in einer komprimierten Datei:
tar -czf [jjjj_Nbhif_aufgabeN_name_vorname].tgz .hg.
jjjj
Die Jahreszahl des Schuljahresbeginns. Für das Schuljahr 2012/13 also 2012.
N
Bei der Klasse, der Jahrgang (also 2bhif, 3bhif) und bei der Aufgabe die Aufgabennummer (aufgabe1, aufgabe2...).
name_vorname
Ihr Name und Vorname in Kleinbuchstaben sowie ohne Umlaute, scharfes s (ß) und Akzente.

Beispiel:
tar -czf 2012_3bhif_aufgabe2_mayer_juergen.tgz .hg


Wir evaluieren gerade ein paar Möglichkeiten für ein zentrales Repository für die Abgabe. Dann braucht man keine Mails mehr schicken. Details folgen...



Weitere Informationen

Labels: , ,


Montag, 17. September 2012

 

Python Aufgaben (POS1: 2BHIF)

Theorie
  1. Was ist ein Dictionary in Python?
  2. Was bedeutet der Begriff "Sequenz" in Python? Geben Sie einige Beispiele.
  3. Wie wird eine Funktion in Python definiert?
  4. Welche Arten der Parameterübergabe gibt es in Python?
  5. Kann eine Python-Funktion mehr als einen Wert (Parameter) ändern bzw. zurückliefern?
    Wenn ja, wie?
  6. Geben Sie ein Beispiel für eine kürzest mögliche Funktion in Python an!
  7. Was ist eine Variable?
  8. Was versteht man unter "Duck Typing"?
  9. Wie werden in Python for-Schleifen gebildet?
  10. Was ist ein Python-Modul? Wofür werden Module verwendet?
  11. Welche Grunddatentypen kennen Sie? Geben Sie auch den Speicherbedarf und den Wertebereich an.
  12. Welche Kontrollstrukturen kennen Sie?
  13. Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente einer Sequenz zu ermitteln, die ein bestimmtes Kriterium (z.B. ist größer als ein bestimmter Wert) erfüllen.
  14. Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente einer Liste von Listen zu ermitteln, die ein bestimmtes Kriterium erfüllen. Z.B. gegeben sei die Liste [[4, 1, 2, 3], [2, 3, 4], [3, 4, 5]]. Erzeugen Sie eine Liste von Elementen, die in allen Teillisten vorkommen.Das Ergebnis wäre bei diesem Beispiel: [3, 4] (sortiert).
  15. Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte einer Sequenz zu ermitteln.
  16. Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte einer Sequenz zu ermitteln.
  17. Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte einer Liste von Listen zu ermitteln.
  18. Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte einer Liste von Listen zu ermitteln.
  19. Wozu benötigt man Kommentare?
  20. Wozu benötigt man Programmierrichtlinien?
Praxis:
Vergleichen Sie Ihre Lösungen mit jenen Ihrer MitschülerInnen.
Hier noch ein paar "Grundübungen", welche Sie als Funktionen plus passender Aufrufe in einem Programm zusammenfassen. Nennen Sie das Programm sequenzen_i99999.py:
  1. Erstellen Sie ein Pythonprogramm, welches das Maximum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten [-1, -23, -2, -32,-89, -100, -1, -99]. Finden Sie weitere Beispieltestdaten.
  2. Erstellen Sie ein Pythonprogramm, welches das Minimum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten [1, 23, 2, 32, 89,100, 1, 99]. Finden Sie weitere Beispieltestdaten.
  3. Erstellen Sie ein Pythonprogramm, welches das Maximum einer Liste von Listen ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten [[1, 23], [2, 32, 89],[100, 1, 99]]. Finden Sie weitere Beispieltestdaten.
  4. Erstellen Sie ein Pythonprogramm, welches das Minimum einer Liste von Listen ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten [[1, 23], [2, 32, 89],[100, 1, 99]]. Finden Sie weitere Beispieltestdaten.
  5. Erstellen Sie ein Pythonprogramm, welches die Häufigkeit von Elementen einer Sequenz (Liste) ermittelt. Definieren Sie dazu eine Testsequenz mit folgenden Werten
    [1, 2,-3, 4, 2, 1, 10, -3, 4, 2, 2, 10] bzw.
    ["hallo", "du", "test", "du","Maus", "test", "Test"].
    Das Ergebnis soll eine Liste von unterschiedlichen Werten sein und wie oft sie vorkommen, absteigend sortiert nach Häufigkeit (häufigstes als erstes).
  6. Folgende Ausgabe soll erzeugt werden: 1 3 5 7 9. Lösen Sie die Aufgabe
    • mithilfe einer while-Schleife
    • mithilfe einer for-Schleife und des Modulo-Operators
    • mithilfe einer for-Schleife ohne den Modulo-Operator
  7. Folgende Ausgabe soll erzeugt werden: 1 2 4 7 11 16 22 29 37. Lösen Sie die Aufgabe
    • mithilfe einer while-Schleife
    • mithilfe einer for-Schleife

Mittwoch, 12. September 2012

 

Java Dokumentation für eclipse einrichten (javadoc, java6)

Standardmäßig bekommt man bei Hilfeaufruf (shift-F2) die Dokumentation direkt von Sun in einem Browserfenster angeboten. Dazu muss das Internet freigesschaltet sein.

Man kann den Pfad für die Doku einstellen. Zum Beispiel befindet sich unter edvodoc/java/docs_6/api/ auch die Java Dokumentation. Der Server edvodoc ist auch im Testbetrieb bzw. bei gesperrtem Internet erreichbar (interner Server!). Die Dokumentation kann natürlich auch in einem lokalen Verzeichnis sein.

Die Einstellung ist im folgenden Bild zu sehen (Window"->"Preferences"->"Installed JREs, dann die entsprechende VM auswählen, Edit, dann .../jre/lib/rt.jar auswählen und Javadoc Location drücken. Dort muss man dann in geeigneter Weise den Pfad auf edvodoc setzen.

Das Bild zeigt die Einrichtung für Java 1.5, aber abgesehen vom Pfad (edvodoc/java/docs_6/api/) funktioniert's genau gleich.

Im Bild ist ein alter URL zu sehen. Aktuell ist http://edvodoc.htlwrn.ac.at/java/docs_6/api/

Labels: ,


Freitag, 7. September 2012

 

Aufgabe Verkette Listen - WH 2. Jg (POS1: 3BHIF)

Abgabename: 2012_3bhif_aufgabe1_Name_Vorname.tgz

Die folgende Aufgabe ermöglichen Ihnen einen Wiedereinstieg in das Programmieren mit Java. Das Rüstzeug zur Lösung sollten Sie in der zweiten Klasse bekommen haben.

Teilnehmerinnen und Teilnehmer melden sich zu einem Tanzkurs an. Der Tanzlehrer stellt die Paare zusammen, indem er immer eine Frau aus der Liste der Teilnehmerinnen und einen Mann aus der Liste der Teilnehmer nimmt (und streicht).

Eine Liste wird immer vollständig leer werden, die zweite kann noch TeilnehmerInnen enthalten.

Aufgabenstellung mit verketteten Listen


Erstellen Sie ein Programm, welches zwei Dateien, in denen die Namen enthalten (einer pro Zeile) sind, liest und die Namen in die entsprechende Liste (alphabetisch sortiert) einfügt.

Die Zusammenstellung der Paare erfolgt dann so, dass jeweils ein (zufälliges) Element aus der ersten Liste und ein (zufälliges) Element aus der zweiten Liste entfernt. Im einfacheren Fall wird das Paar einfach ausgegeben und die beiden Listenelemente freigegeben (alle Referenzen auf die Listenelemente auf null setzen, sodass der Garbage Collector den Speicher freigeben kann). In der fortgeschrittenen Lösung wird das Paar in eine spezielle Liste übernommen, deren Elemente jeweils Referenzen auf die beiden Teilnehmer enthält. Zum Schluss wird diese Liste ausgegeben.

Mögliche Datenstrukturen


class Participant {
   Participant next;
   String name;
}
An geeigneter Stelle sollte es etwas wie folgt geben:
Participant women = null;
Participant men = null;

Für Paare wird es eine eigene Datenstruktur (Klasse) geben:
class DanceCouple {
   DanceCouple next;
   Participant woman;
   Participant man;
}
An geeigneter Stelle sollte es etwas wie folgt geben:
DanceCouple danceCouples = null;

Gesamtprogramm und Tests


Aufrufbeispiel bei zufälliger Auswahl der Tanzpartner:
hp@l211 $ java DanceCourse male female
   6 dance couples
   ===============

   Felix <-> Petra
   Franz <-> Sonja
  Harald <-> Elke
  Martin <-> Gabi
   Peter <-> Karin
Reinhold <-> Brigitte

      leftover
      ========

       Andrea

Dabei enthält die Datei male die Namen der Männer und female die Namen der Frauen:
male
Harald
Franz
Martin
Felix
Peter
Reinhold
female
Gabi
Elke
Sonja
Brigitte
Karin
Petra
Andrea

Nach dem Einlesen der Dateien sollten zwei Listen, etwa wie im Bild skizziert, enstehen:

Die Zuordnung der Paare erzeugt eine Liste wie folgt. Eine Dame bleibt bei in der Liste frauen:
Schreiben Sie für die Ausgabe der Überschriften eine Methode, welche einen String als Parameter hat. Dieser String soll ausgegeben werden und darunter genauso viele = als der String lang ist.
printHeader("dance class");
printHeader("list of couples");
printHeader("center", 20); // print "center" centered within a 20 char line
erzeugt:
dance class
===========
list of couples
===============
       center
       ======
Die Liste der Paare soll ebenfalls zentriert ausgegeben werden. Bestimmen Sie dazu die längste Zeile der Art
Mann <-> Frau
und verwenden Sie diesen Wert als Zeilenlänge (auch für die zentrierte Überschrift).

Abgabe und Versionsverwaltung

Details folgen noch an dieser Stelle.

Labels: , ,


Donnerstag, 6. September 2012

 

Wiederholung Python (POS1: 2BHIF)

Abgabename: 2012_2bhif_aufgabe1_Name_Vorname.tgz

Die folgenden Aufgaben ermöglichen Ihnen einen Wiedereinstieg in das Programmieren mit Python. Das Rüstzeug zu Lösung sollten Sie in der ersten Klasse bekommen haben.
Googlen Sie nach 'python "reference card"' und suchen Sie eine passende Kurzreferenz.
  1. Schreiben Sie eine Funktion input_sentences in einem Modul text_analyzer, die den Benutzer nach beliebigen Sätzen fragt, diese in einer Liste abspeichert und danach zurückliefert. Das könnte also so aussehen:
    Bitte geben Sie die zu analysierenden Sätze ein (CTRL-D bricht ab):
    Satz: Maxi und Mini verliefen sich im Wald, aber bald.
    Satz: 10 alte Fledermäuse flogen im Wald
    Satz: Hat die alte Meisterhexe...
    Satz: Seid's gewesen. Denn als Geister...
    Satz: Erst hervor der alte Meister.
    Satz: <ctrl-d>
    
  2. Fügen Sie dazu in diesem Modul einen Aufruf dieser Funktion ein, sodass das Modul sowohl als Modul als auch als Programm verwendet werden kann.
  3. Schreiben Sie eine Funktion split_sentences(lst), die eine Liste solcher Sätze bekommt und eine Liste von Wortlisten zurückliefert, wobei die übergebene Liste lst direkt verändert werden soll.

    Die Wortlisten entstehen indem man die Sätze an den Whitespace Zeichen und den Satzzeichen ("',;.:-) trennt. Die Satzzeichen werden nicht benötigt.

    Gehen Sie dazu folgendermaßen vor:
    1. Ersetze zuerst alle Satzzeichen hintereinander durch Leerzeichen. Verwende dazu die replace Methode des Typs str.
    2. Trenne (splitte) danach den String in die einzelnen Wörter mittels der Methode split des Typs str.
    Für die obigen Daten sieht das Ergebnis dieses Funktionsaufrufes folgendermaßen aus:
    >>> lst = ['Maxi und Mini verliefen sich im Wald, aber bald.',
    ... '10 alte Fledermäuse flogen im Wald',
    ... 'Hat die alte Meisterhexe...',
    ... "Seid's gewesen. Denn als Geister...",
    ... 'Erst hervor der alte Meister.']
    >>> split_sentences(lst)
    [['Maxi', 'und', 'Mini', 'verliefen', 'sich', 'im', 'Wald',\
    'aber', 'bald'], ['10', 'alte', 'Fledermäuse', 'flogen', 'im', 'Wald'],\
    ['Hat', 'die', 'alte', 'Meisterhexe'], ['Seid', 's', 'gewesen', 'Denn',\
    'als', 'Geister'], ['Erst', 'hervor', 'der', 'alte', 'Meister']]
    >>> lst
    [['Maxi', 'und', 'Mini', 'verliefen', 'sich', 'im', 'Wald',\
    'aber', 'bald'], ['10', 'alte', 'Fledermäuse', 'flogen', 'im', 'Wald'],\
    ['Hat', 'die', 'alte', 'Meisterhexe'], ['Seid', 's', 'gewesen', 'Denn',\
    'als', 'Geister'], ['Erst', 'hervor', 'der', 'alte', 'Meister']]
    
    Bei der obigen Ausgabe wurden zur besseren Lesbarkeit die Zeilen manuell umgebrochen und der Zeilenumbruch jeweils mit einem \ gekennzeichnet.

    Baue diese Funktion in das Hauptprogramm ein.
  4. Schreiben Sie eine Funktion purge_bad_words(lst), die eine Liste von Listen von Wörtern erhält und alle diejenigen herauslöscht, die
    • weniger als 2 Zeichen lang sind oder
    • nicht alphabetische Zeichen enthalten
    Die übergebene Liste lst soll direkt manipuliert und auch zurückgeliefert werden:
    >>> purge_bad_words(lst)
    [['Maxi', 'und', 'Mini', 'verliefen', 'sich', 'im', 'Wald', 'aber',\
    'bald'], ['alte', 'Fledermäuse', 'flogen', 'im', 'Wald'], ['Hat',\
    'die', 'alte', 'Meisterhexe'], ['Seid', 'gewesen', 'Denn', 'als',\
    'Geister'], ['Erst', 'hervor', 'der', 'alte', 'Meister']]
    
    Wie leicht zu sehen sind sind die zu kurzen Wörter und die Wörter, die nicht-alphabetische Zeichen enthalten entfernt worden.
  5. Schreiben Sie eine Funktion analyze_words(lst), die eine Liste wie aus dem vorhergehenden Punkt als Argument bekommt und ein Dictionary mit allen Worten als Keys und deren Häufigkeiten als Values zurückliefert, wobei aber alle Wörter nur klein geschrieben gezählt werden:
    >>> analyze_words(lst)
    {'wald': 2, 'mini': 1, 'aber': 1, 'gewesen': 1, 'flogen': 1, 'im': 2,\
    'hervor': 1, 'als': 1, 'verliefen': 1, 'maxi': 1, 'sich': 1,\
    'meister': 1, 'hat': 1, 'bald': 1, 'meisterhexe': 1, 'erst': 1,\
    'fledermäuse': 1, 'geister': 1, 'die': 1, 'alte': 3, 'und': 1,\
    'denn': 1, 'seid': 1, 'der': 1}
    

  6. Schreiben Sie eine Funktion analyze_letters(lst), die wiederum eine Liste der Liste der Wörter bekommt und ein Dictionary mit Buchstaben als Keys und deren Häufigkeiten als Values zurückliefert. Wiederum werden alle Buchstaben als Kleinbuchstaben betrachtet:
    >>> analyze_letters(lst)
    {'a': 10, 'c': 1, 'b': 2, 'e': 28, 'd': 9, 'g': 3, 'f': 3, 'i': 12,\
    'h': 4, 'm': 7, 'l': 10, 'o': 2, 'n': 7, 's': 9, 'r': 10, 'u': 2,\
    't': 8, 'w': 3, 'v': 2, 'x': 2, 'ä': 1}
    

  7. Schreiben Sie nun eine Funktion purge_analyzed_letters(dic), die alle Umlaute (ä, ü, ö) aus dem Dictionary (des vorhergehenden Punktes) entfernt:
    >>> purge_analyzed_letters(dic)
    {'a': 10, 'c': 1, 'b': 2, 'e': 28, 'd': 9, 'g': 3, 'f': 3, 'i': 12,\
    'h': 4, 'm': 7, 'l': 10, 'o': 2, 'n': 7, 's': 9, 'r': 10, 'u': 2,\
    't': 8, 'w': 3, 'v': 2, 'x': 2}
    

  8. Entwicklen Sie eine Funktion sort_letters(dic), die ein Dictionary wie aus dem vorhergehenden Punkt bekommt und eine absteigend sortierte Liste von Tupel mit Buchstabe und Häufigkeit zurückliefert:
    >>> sort_letters(dic)
    [('e', 28), ('i', 12), ('a', 10), ('l', 10), ('r', 10), ('d', 9),\
    ('s', 9), ('t', 8), ('m', 7), ('n', 7), ('h', 4), ('g', 3), ('f', 3),\
    ('w', 3), ('b', 2), ('o', 2), ('u', 2), ('v', 2), ('x', 2), ('c', 1)]
    

  9. Probieren Sie aus:
    1. "abcdef".index("c")
    2. "abcdef".index("g")
    3. "abcdef".index("de")
    4. "c" in "abcdef"
    5. "g" in "abcdef"
    6. "de" in "abcdef"
    7. "abcdef"[2:4]
    8. "abcdef"[2:]
    9. "abcdef"[-1]
    10. "abcdef"[2:-1]
    11. [1, 2, 3, 4, 5].index(3)
    12. [1, 2, 3, 4, 5].index(9)
    13. [1, 2, 3, 4, 5][5]
    14. [1, 2, 3, 4, 5][2:4]
    15. [1, 2, 3, 4, 5][-2]
    16. [1, 2, 3, 4, 5][5:9]
    17. [1, 2, 3, 4, 5][4:]
    18. len("abc") + len(range(3)) + len({1, 2, 3}) + len({1: 2, 2: 3})

  10. Bauen Sie in ihr Main Testaufrufe aller Funktionen mit einer fixen Liste auf (Kommentieren Sie den Aufruf von input_sentences() aus). Es soll jedes Stadium der Verarbeitung der Liste ausgegeben werden. Bauen Sie die Aufrufe aus obigem Punkt (Probieren Sie aus) ein und geben Sie das Ergebnis aus. Man muss den Programmcode (print() verwenden) sehen und das Ergebnis.

  11. Geben Sie das Beispiel ab, indem Sie text_analyzer.py per Mail an mich senden.


Das Original zu dieser Aufgabe stammt von Dr. Kolousek.

Labels: , ,


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

Abonnieren Posts [Atom]