30 Ekim 2011 Pazar

Eprog StringCompressor

  1. Entpacken der StringCompressor.jar
  2. Angabe öffnen, mit der Console (cmd.exe) ins Verzeichnis “impl” springen und mittels “javac StringCompressor.java && javac UncompressedString.java && java StringCompressor” das ganze mal durchkompilieren und testen obs funktioniert soweit, Ausgabe hier sollte “” (nichts also!) sein.
  3. Also laut eingabe sollen wir: In der main-Methode der Klasse StringCompressor wird von der Standardeingabe (System.in) ein String eingelesen. Sie können davon ausgehen, dass die Eingabe nur aus den Zeichen ‘a’-'z’ besteht und keine Leerzeichen enthält. Übergeben Sie die eingelesene Zeichenkette als String dem Konstruktor der Klasse UncompressedString.
    Das ganze sind 2 Zeilen in der main Methode:
public static void main (String [] args)
{
    Scanner s = new Scanner(System.in);
    UncompressedString str = new UncompressedString(s.next());
    }

Nun heißt es in der Angabe: Nach dem Einlesen der Zeichenkette erwartet das Programm bis zum Ende der Eingabe (EOF) beliebig viele der folgenden Befehle in beliebiger Reihenfolge.
Das bedeutet für uns nun folgendes in der Main Methode:

public static void main (String [] args)
    {
        Scanner s = new Scanner(System.in);
        UncompressedString str = new UncompressedString(s.next());
        while(s.hasNextLine())
        {
            String cmd = s.next();
            //Damit bekommen wir den nächsten String rein (Achtung ein leerzeichen resultiert in mehre Elemente Wenn
            //z.b. der Input String "abc def" ist steht in cmd nur "abc" und mit erneuten aufruf von s.next() erhält man "def"

            if(cmd.equalsIgnoreCase("count"))
            {
            }
            else if(cmd.equalsIgnoreCase("ratio"))
            {
            }
            else if(cmd.equalsIgnoreCase("compress"))
            {
            }
            else
                System.out.println("UNKNOWN COMMAND");
        }
    }



Laut Angabe sollen wir nun die Befehle unserer Klasse UncompressString zuordnen dafür müssen wir nur die Methoden der Klasse aufrufen:



if(cmd.equalsIgnoreCase("count"))
            {
                String count = s.next(); //Lesen wir mal ein was als paramenter übegeben wurde
                if(count.length() == 1 && Character.isLetter(count.charAt(0))) //Der String der hinter count kommt darf nur 1 Zeichen lang sein und muss ein Buchstabe sein
                    System.out.println(str.count(count.charAt(0))); //Ausgeben der Anzahl
                else
                    System.out.println("INVALID PARAMETER"); //Fehlermeldung ausgeben
            }
            else if(cmd.equalsIgnoreCase("ratio"))
            {
                System.out.println(str.ratio());
            }
            else if(cmd.equalsIgnoreCase("compress"))
            {
                System.out.println(str.compress());
            }
            else
                System.out.println("UNKNOWN COMMAND");



Lauflängenkodierung
Auf zum interessanten Teil der Übung,  das ganze wird nun in der Methode “Compress” gemacht, aber zuerst noch ein wenig Vorarbeit im Konstruktor der Klasse



public class UncompressedString {

    // Das zulaessige Alphabet
    public static String alphabet = "abcdefghijklmnopqrstuvwxyz";
    private String str = "";

    /**
    * Erzeugt einen neuen UncompressedString mit der als String
    * uebergebenen Zeichenkette und speichert diese.
    *
    * @param letters
    *     Der eingelesene String an Buchstaben
    */
    public UncompressedString (String letters)
    {
        str = letters;
    }


Wir erstellen einmal eine private Membervariable vom Typ String und weißen diese im Konstruktor zu.
Die Funktion compress habe ich folgendermaßen gelöst:



Die Methode Count sieht folgendermaßen aus:
j
public int count(char c)
    {
        int count = 0;
        for(int i = 0 ; i < str.length(); i++)
        {
            if(str.charAt(i) == c)
                count++;
        }
        return count;
    }

Die Methode Ratio ist genauso relativ einfach

public double ratio()
    {
        double first = 0.0;
        double last = 0.0;
        for(int i = 0; i < str.length(); i++)
        {
            if(str.charAt(i) < 'n')
                first++;
            else
                last++;
        }
        return first / last;
    }



Nun fehlt nur noch die toString Methode:
j

public String toString()
 {
  return str;
 }
 
 
Der gesamte Quellcode:
StingCompressor:

import java.util.Scanner;

/**
 * Diese Klasse ist ausfuehrbar und beinhaltet daher die
 * main-Methode. Sie verarbeitet die Eingaben, erzeugt das
 * Objekt vom Typ UncompressedString und generiert Ausgaben.
 */
public class StringCompressor {

    /**
    * Liest die Daten ein und gibt das Ergebnis aus. Allein
    * diese Methode liest direkt von System.in ein und gibt
    * direkt auf System.out aus.
    */
    public static void main (String [] args)
    {
        Scanner s = new Scanner(System.in);
        UncompressedString str = new UncompressedString(s.next());
        while(s.hasNextLine())
        {
            String cmd = s.next();
            //Damit bekommen wir den nächsten String rein (Achtung ein leerzeichen resultiert in mehre Elemente Wenn
            //z.b. der Input String "abc def" ist steht in cmd nur "abc" und mit erneuten aufruf von s.next() erhält man "def"

            if(cmd.equalsIgnoreCase("count"))
            {
                String count = s.next(); //Lesen wir mal ein was als paramenter übegeben wurde
                if(count.length() == 1 && Character.isLetter(count.charAt(0))) //Der String der hinter count kommt darf nur 1 Zeichen lang sein und muss ein Buchstabe sein
                    System.out.println(str.count(count.charAt(0))); //Ausgeben der Anzahl
                else
                    System.out.println("INVALID PARAMETER"); //Fehlermeldung ausgeben
            }
            else if(cmd.equalsIgnoreCase("ratio"))
            {
                System.out.println(str.ratio());
            }
            else if(cmd.equalsIgnoreCase("compress"))
            {
                System.out.println(str.compress());
            }
            else
                System.out.println("UNKNOWN COMMAND");
        }
    }
}


UncompressedString:

/**
 * Diese Klasse repraesentiert einen String, der nur
 * Kleinbuchstaben enthaelt. Sie bietet weiters entsprechende
 * Methoden zur Abfrage der Eigenschaften. Diese Klasse
 * liest weder direkt von System.in ein, noch gibt sie
 * direkt auf System.out aus.
 */
public class UncompressedString {

    // Das zulaessige Alphabet
    public static String alphabet = "abcdefghijklmnopqrstuvwxyz";
    private String str = "";

    /**
    * Erzeugt einen neuen UncompressedString mit der als String
    * uebergebenen Zeichenkette und speichert diese.
    *
    * @param letters
    *     Der eingelesene String an Buchstaben
    */
    public UncompressedString (String letters)
    {
        str = letters;
    }

    /**
    * Erwartet ein Zeichen c als Argument und bestimmt die
    * Anzahl der Vorkommnisse dieses Zeichens in der
    * gespeicherten Zeichenkette. Ist diese beispielsweise
    * "eeedaaeeb" und die Methode count wird mit dem Argument
    * 'e' aufgerufen, so wird 5 zurueckgegeben.
    *
    * @param c
    *     Das zu zaehlende Zeichen
    * @return
    *     Die Anzahl an Vorkommen des uebergebenen Zeichens
    */
    public int count(char c)
    {
        int count = 0;
        for(int i = 0 ; i < str.length(); i++)
        {
            if(str.charAt(i) == c)
                count++;
        }
        return count;
    }

    /**
    * Bestimmt das Verhaeltnis zwischen in der gespeicherten
    * Zeichenkette vorkommenden Zeichen aus der ersten Haelfte
    * des Alphabets ('a'-'m') und vorkommenden Zeichen aus der
    * zweiten Haelfte des Alphabets ('n'-'z'). Wurde
    * beispielsweise ein UncompressedString mit "axbcz"
    * erzeugt, so liefert diese Methode den Wert 3:2=1.5 zurueck
    * (drei Zeichen stammen aus der ersten Haelfte des
    * Alphabets, zwei Zeichen aus der zweiten Haelfte).  Sie
    * koennen davon ausgehen, dass zumindest je ein Zeichen aus
    * beiden Haelften des Alphabets vorkommt.
    *
    * @return
    *     Das Verhaeltnis der Anzahl von Zeichen in der ersten
    *     Haelfte des Alphabets zu Zeichen in der zweiten Haelfte
    *     des Alphabets
    */
    public double ratio()
    {
        double first = 0.0;
        double last = 0.0;
        for(int i = 0; i < str.length(); i++)
        {
            if(str.charAt(i) < 'n')
                first++;
            else
                last++;
        }
        return first / last;
    }

    /**
    * Liefert eine komprimierte Darstellung der gespeicherten
    * Zeichenkette unter Anwendung von Lauflaengenkodierung
    * als String zurueck, die gespeicherte Zeichenkette selbst
    * wird nicht veraendert. Eine Folge gleicher Zeichen wird
    * durch deren Laenge als Zahl gefolgt vom Zeichen selbst
    * dargestellt. Beispielsweise wird aus "eeeeaaa" der
    * komprimierte String "4e3a". Bei Folgen mit Laenge 1 wird
    * die Laengenangabe weggelassen. Beispiel: Das Ergebnis
    * der Komprimierung von "eeeedaaa" ist "4ed3a".
    *
    * @return
    *     Der komprimierte String
    */
    public String compress()
    {
        String res = ""; //Diesen String geben wir zurück

        //Checken wir unseren String also mal durch
        for(int i = 0; i < str.length(); i++) //gehen wir jeden Buchstaben durch beispielstring aaabbc (Ergebnis sollte hierbei sein 3a2bc)
        {
            int CountOfThisLetter = 0; //Wieoft gibts diesen Buchstaben ?
            int index = 0;
            //So dann Zählen wir mal
            for(int j = 0; j < str.length() - i; j++)
            {
                if(str.charAt(i) == str.charAt(i+j)) //Der Buchstabe den wir in der ÄußerenSchleife (i) gerade bearbeiten wird gezählt, achtung aufs ende!
                    CountOfThisLetter++;
                else
                    break; //Der darauffolgende Buchstabe ist falsch! Brich diese schleife ab
            }

            if(CountOfThisLetter > 1) //Den Buchstaben gibts öfter als einmal also fügen wir die Anzahl davor ein
                res += CountOfThisLetter + String.valueOf(str.charAt(i));
            else //Ohne Anzahl da es nur einen buchstaen gibt
                res += String.valueOf(str.charAt(i));

            i += CountOfThisLetter - 1;
        }
        return res;
    }

    /**
    * Gibt die gespeicherte unkomprimierte Zeichenkette als
    * String zurueck.
    *
    * @return
    *     Eine lesbare Repraesentation dieses Objekts
    */
    public String toString()
    {
        return str;
    }

}



Hiç yorum yok:

Yorum Gönder