Sitzung: Jeden Freitag in der Vorlesungszeit ab 16 Uhr c. t. im MAR 0.005. In der vorlesungsfreien Zeit unregelmäßig (Jemensch da?). Macht mit!

Javakurs/Übungsaufgaben/Cäsar-Chiffre/Musterlösung: Unterschied zwischen den Versionen

 
Zeile 20: Zeile 20:
 
     int menuCase;
 
     int menuCase;
  
     String text= new String();
+
     String text= "";
 
     String textState= "nothing loaded";
 
     String textState= "nothing loaded";
     String output= new String(); /*will always be shown under menu*/
+
     String output= ""; /*will always be shown under menu*/
 
     int key;
 
     int key;
  
Zeile 47: Zeile 47:
 
     String s= readln();
 
     String s= readln();
  
     menuCase= Integer.valueOf(s).intValue();
+
     menuCase= Integer.parseInt(s);
  
  
Zeile 91: Zeile 91:
 
               {
 
               {
 
                 System.out.print("key: ");
 
                 System.out.print("key: ");
                 key= Integer.valueOf(readln()).intValue();
+
                 key= Integer.parseInt(readln());
  
 
                 text= encryptCaesar(text, key);
 
                 text= encryptCaesar(text, key);
Zeile 111: Zeile 111:
 
                 text= decryptCaesar(text, key);
 
                 text= decryptCaesar(text, key);
 
   
 
   
                 output= new String("key is: "+ key);
+
                 output= "key is: "+ key;
 
                 textState= "decrypted";
 
                 textState= "decrypted";
  
Zeile 122: Zeile 122:
 
               {
 
               {
 
                 System.out.print("key: ");
 
                 System.out.print("key: ");
                 key= Integer.valueOf(readln()).intValue();
+
                 key= Integer.parseInt(readln());
  
 
                 text= decryptCaesar(text, key);
 
                 text= decryptCaesar(text, key);
Zeile 223: Zeile 223:
  
 
      
 
      
     String text= new String();
+
     String text= "";
  
  
Zeile 232: Zeile 232:
 
       BufferedReader buff = new BufferedReader(file);
 
       BufferedReader buff = new BufferedReader(file);
  
      boolean eof = false;
 
  
 
+
       while ( true ) {
       while ( !eof ) {
 
  
 
         String line = buff.readLine();
 
         String line = buff.readLine();
Zeile 241: Zeile 239:
 
         if ( null == line ) {
 
         if ( null == line ) {
  
             eof = true;
+
             break;
  
 
         } else {
 
         } else {
Zeile 272: Zeile 270:
  
 
   String originLowCase= origin.toLowerCase();
 
   String originLowCase= origin.toLowerCase();
   String text= new String();
+
   String text= "";
  
  
Zeile 278: Zeile 276:
 
     /* filtering signs 'a' to 'z' using ASCII numbers */
 
     /* filtering signs 'a' to 'z' using ASCII numbers */
  
     if (  ((int) originLowCase.charAt(i)>= 97)  
+
     if (  (originLowCase.charAt(i)>= 'a')  
         && ((int) originLowCase.charAt(i)<= 122) )
+
         && (originLowCase.charAt(i)<= 'z') )
  
 
     text+= originLowCase.charAt(i);
 
     text+= originLowCase.charAt(i);
Zeile 300: Zeile 298:
 
     * number of chars in text*/
 
     * number of chars in text*/
  
     int chr[]= new int[27];   
+
     int[] chr= new int[27];   
  
  
Zeile 306: Zeile 304:
 
     for ( int j= 0; j< text.length(); j++ ) {
 
     for ( int j= 0; j< text.length(); j++ ) {
  
       chr[ ((int) text.charAt(j)) - 97 ]++;
+
       chr[ text.charAt(j) - 'a' ]++;
  
 
       chr[26]++;
 
       chr[26]++;
Zeile 331: Zeile 329:
 
     * number of chars in text*/
 
     * number of chars in text*/
  
     int chr[]= frequencyAnalysis(text);
+
     int[] chr= frequencyAnalysis(text);
  
  
Zeile 514: Zeile 512:
  
 
      
 
      
   String text= new String();
+
   String text= "";
 
   /* number of occurence of most frequent char: */
 
   /* number of occurence of most frequent char: */
  
Zeile 522: Zeile 520:
  
  
   char en[]= {'e','t','a',};  //most frequent letters in english
+
   char[] en= {'e','t','a',};  //most frequent letters in english
  
   char ge[]= {'e','n','i',};  //most frequent letters in german
+
   char[] ge= {'e','n','i',};  //most frequent letters in german
  
  
Zeile 558: Zeile 556:
 
   /* define most frequent char */
 
   /* define most frequent char */
  
   int chr[]= frequencyAnalysis(origin);
+
   int[] chr= frequencyAnalysis(origin);
  
  
Zeile 583: Zeile 581:
 
       /*assumed char causes certain displacement */
 
       /*assumed char causes certain displacement */
  
       displacement= (mostFrequentChr+97) -  (int) en[k]  ;   
+
       displacement= (mostFrequentChr+'a') -  (int) en[k]  ;   
  
 
     } else {
 
     } else {
  
       displacement= (mostFrequentChr+97) -  (int) ge[k]  ;
+
       displacement= (mostFrequentChr+'a') -  (int) ge[k]  ;
  
 
     }
 
     }
Zeile 630: Zeile 628:
  
 
   public static String encryptCaesar( String text, int key ) {
 
   public static String encryptCaesar( String text, int key ) {
     return ( modifyText(text, key) );
+
     return modifyText(text, key);
 
   }
 
   }
  
 
   public static String decryptCaesar( String text, int key ) {
 
   public static String decryptCaesar( String text, int key ) {
     key= key*(-1);
+
     key*= -1;
     return ( modifyText(text, key) );
+
     return modifyText(text, key);
 
   }
 
   }
  
  
 
   public static String modifyText( String text, int key ) {
 
   public static String modifyText( String text, int key ) {
     String encrypted= new String("");
+
     String encrypted= "";
 
    
 
    
     key= key%26;
+
     key%= 26;
 
 
    int code= 0;
 
    int currentChar= 0;
 
  
 
     for ( int i= 0; i< text.length(); i++ ) {
 
     for ( int i= 0; i< text.length(); i++ ) {
  
       currentChar= (int) text.charAt(i);
+
       int currentChar= (int) text.charAt(i);
       code= currentChar;
+
       int code= currentChar;
  
 
       /*lower case letters*/
 
       /*lower case letters*/

Aktuelle Version vom 27. Mai 2011, 09:13 Uhr


/* Decodes texts having been encoded with caesar */




import java.io.*;


public class Caesar {


     public static void main(String arg[])

   {



    int menuCase;

    String text= "";
    String textState= "nothing loaded";
    String output= ""; /*will always be shown under menu*/
    int key;


    do

    {

     System.out.println("[1] load text");
     System.out.println("[2] show text");
     System.out.println("[3] save text");
     System.out.println("[4] encrypt text");
     System.out.println("[5] decrypt text without key");
     System.out.println("[6] decrypt text with key");
     System.out.println("[7] quit");
     System.out.println( );
     System.out.println("text state: ["+ textState +"]");

     System.out.println( );
     System.out.println( output );

     System.out.print("input: ");

     String s= readln();

     menuCase= Integer.parseInt(s);



     switch (menuCase) {

        case 1:

               {

                  System.out.print("filename: ");

                  String fileIn= readln();


                  text= readFile(fileIn);
 
                  output = "";
                  textState= "loaded";

                  break;

               }

        case 2: 
               {
                  output= text;
                  break;
               }
        case 3: 
               {
                  System.out.print("filename: ");

                  String fileName= readln();

                  String[] fileToSave= {text};
                  writeArrayToFile( fileName, fileToSave );

                  output = "";
                  break;
               }
        case 4:
               {
                 System.out.print("key: ");
                 key= Integer.parseInt(readln());

                 text= encryptCaesar(text, key);

                 output = "";
                 textState= "encrypted";
                 break;
               }
        case 5:

               {
                 if( determineKoinzidenzindex(text) < 0.06 ) {
                   output= "Text might not be Caesar encrypted! ";
                 }


                 key= findKeyCaesar(text);

                 text= decryptCaesar(text, key);
 
                 output= "key is: "+ key;
                 textState= "decrypted";


                 break;

               }
        case 6:

               {
                 System.out.print("key: ");
                 key= Integer.parseInt(readln());

                 text= decryptCaesar(text, key);

                 output = "";
                 textState= "decrypted";


                 break;

               }

       }//switch


   }while(menuCase!=7);

  } //main


  /* reads in a text from console */

  public static String readln() {


    BufferedReader consoleLine =

    new BufferedReader(new InputStreamReader(System.in));

    String input = null;

    try {

      input = consoleLine.readLine();

    } catch (IOException e) {

      e.printStackTrace();

    }

      return input;

  }


  /**

   * Schreibt einen String-Array in eine Datei. 

    * @param filename : Pfad zu der Datei in Form eines Strings,
                        also z.B. "hallo.txt" oder "/etc/fstab", ...
    * @param data String-Array: welches in die angegebene Datei 
                                geschrieben werden soll.
    * @return
    */

  public static boolean writeArrayToFile(String filename, 
                                         String[] data   ) {

    BufferedWriter bufferedWriter;

    try {

      // Datei zum schreiben oeffnen

      bufferedWriter= new BufferedWriter(

           new OutputStreamWriter( new FileOutputStream(filename)) );

		

    // Array Elementenweise in Datei schreiben
    for (int i = 0; i < data.length; i++) {

      bufferedWriter.write(data[i]);
      bufferedWriter.newLine();

    }

    bufferedWriter.flush();
	

    } catch (Exception e) {
      // Fehlerbehandlung

      e.printStackTrace();
      return false;

    }

      return true;		
  }



  /* reads in a text */

  public static String readFile( String fileName ) {

    
    String text= "";


    try {

      FileReader file = new FileReader (fileName);

      BufferedReader buff = new BufferedReader(file);


      while ( true ) {

        String line = buff.readLine();

        if ( null == line ) {

             break;

        } else {

          text+= line;

        }

      }


     buff.close();


    } catch (IOException e) {

      System.out.println( e.toString() );

    }

   return text;

  }

                                                                   
  /* takes out punctuation and sets all letters to lower case */

  public static String takeOutPunctuation( String origin ) {


   String originLowCase= origin.toLowerCase();
   String text= "";


   for ( int i= 0; i<originLowCase.length(); i++ ) {
     /* filtering signs 'a' to 'z' using ASCII numbers */

     if (   (originLowCase.charAt(i)>= 'a') 
         && (originLowCase.charAt(i)<= 'z') )

     text+= originLowCase.charAt(i);
   }


   return text;

  }







  public static int[] frequencyAnalysis( String text ) {

    /* holds frequency of chars a-z, last digit (index 26) is total 
     * number of chars in text*/

    int[] chr= new int[27];  



    for ( int j= 0; j< text.length(); j++ ) {

      chr[ text.charAt(j) - 'a' ]++;

      chr[26]++;

    }


   return chr;

  }


  /*see also: http://de.wikipedia.org/wiki/Koinzidenzindex */  

  public static double determineKoinzidenzindex( String text ) {

    text= takeOutPunctuation( text );


    int cnt= 0; 
    double kindex= 0;

    /* holds frequency of chars a-z, last digit (index 26) is total 
     * number of chars in text*/

    int[] chr= frequencyAnalysis(text);


    /* chr.length-1 remember: last digit holds number of chars */

    for ( int k= 0; k< chr.length-1; k++ ) {

      kindex+= ( ((double) chr[k]/chr[26])*((double) chr[k]/chr[26]));

    }



    return kindex;

  }

  /* count the number of nigramms and trigramms  in a german text*/

  public static int germanText( String text ) {

  

    int cntbitri= 0; //counter for bi- and trigramms

    
    /* count bigramms */

    for ( int i= 0; i< text.length()-1; i++ ) {

        if (

            (text.substring(i, i+2).equals("er"))

            ||(text.substring(i, i+2).equals("en"))

            ||(text.substring(i, i+2).equals("ch"))

            ||(text.substring(i, i+2).equals("de"))

            ||(text.substring(i, i+2).equals("ei"))

            ||(text.substring(i, i+2).equals("nd"))

            ||(text.substring(i, i+2).equals("te"))

            ||(text.substring(i, i+2).equals("in"))

            ||(text.substring(i, i+2).equals("ie"))

            ||(text.substring(i, i+2).equals("ge"))

           )

             cntbitri++;

    }


   /* count trigramms */

   for ( int i= 0; i< text.length()-2; i++ ) {

     if (

          (text.substring(i, i+3).equals("ein"))

          ||(text.substring(i, i+3).equals("ich"))

          ||(text.substring(i, i+3).equals("nde"))

          ||(text.substring(i, i+3).equals("die"))

          ||(text.substring(i, i+3).equals("und"))

          ||(text.substring(i, i+3).equals("der"))

          ||(text.substring(i, i+3).equals("che"))

          ||(text.substring(i, i+3).equals("end"))

          ||(text.substring(i, i+3).equals("gen"))

          ||(text.substring(i, i+3).equals("sch"))

         ) cntbitri++;

   }

   return cntbitri;

  }


  /* count the number of nigramms and trigramms in an english text*/

  public static int englishText( String text ) {

    int cntbitri= 0; /*counter for bi- and trigramms */

   
   /* count bigramms */

   for ( int i= 0; i< text.length()-1; i++ ) {

     if (

          (text.substring(i, i+2).equals("th"))

          ||(text.substring(i, i+2).equals("he"))

          ||(text.substring(i, i+2).equals("an"))

          ||(text.substring(i, i+2).equals("in"))

          ||(text.substring(i, i+2).equals("er"))

          ||(text.substring(i, i+2).equals("re"))

          ||(text.substring(i, i+2).equals("on"))

          ||(text.substring(i, i+2).equals("es"))

          ||(text.substring(i, i+2).equals("ti"))

          ||(text.substring(i, i+2).equals("at"))

         )

       cntbitri++;

   }



   /* count trigramms */

   for (int i= 0; i< text.length()-2; i++) {

     if (

          (text.substring(i, i+3).equals("the"))

          ||(text.substring(i, i+3).equals("ing"))

          ||(text.substring(i, i+3).equals("and"))

          ||(text.substring(i, i+3).equals("ion"))

          ||(text.substring(i, i+3).equals("tio"))

          ||(text.substring(i, i+3).equals("ent"))

          ||(text.substring(i, i+3).equals("ere"))

          ||(text.substring(i, i+3).equals("her"))

          ||(text.substring(i, i+3).equals("ate"))

          ||(text.substring(i, i+3).equals("ver"))

     ) cntbitri++;

   }

   return cntbitri;

  }



  public static int findKeyCaesar(String origin) {
    /* proccedding:

     * search for most frequent char in encoded text and assume it is
     * one of the three most frequent letters in german or english
     * language.

     * decode text end test if it is decipheable
     */
   origin= takeOutPunctuation( origin );

     
   String text= "";
   /* number of occurence of most frequent char: */

   int mostFrequentChrValue= 0;

   int mostFrequentChr= 0;     //most frequent char in text


   char[] en= {'e','t','a',};  //most frequent letters in english

   char[] ge= {'e','n','i',};  //most frequent letters in german


   int biTriMax= 0;            //maximal value of bi- and trigramms

   int biTriTemp= 0;


   int displacement= 0;
   int key= 0;

   double kindex= determineKoinzidenzindex(origin);

     

/*

    System.out.print("Koinzidenzindex: "+ kindex );

    if ( kindex < 0.07 ) {

       System.out.println( " english text" );

    } else {

        System.out.println(" german text" );
    }

    System.out.println( );

*/

   /* define most frequent char */

   int[] chr= frequencyAnalysis(origin);



   for ( int i= 0; i< chr.length-1; i++) {

     if ( mostFrequentChrValue< chr[i] ) {

       mostFrequentChrValue= chr[i];

       mostFrequentChr= i;

     }

   }//for

   
   /*assume most frequent char as (e,t,a)(engl.) or (e,n,i)(germ.) */

   for ( int k= 0; k< en.length; k++ ) {
      /* decide if text german or english */

     if ( kindex < 0.07 ) {
       /*assumed char causes certain displacement */

       displacement= (mostFrequentChr+'a') -  (int) en[k]  ;   

     } else {

       displacement= (mostFrequentChr+'a') -  (int) ge[k]  ;

     }


     if ( kindex < 0.07) {

       text= decryptCaesar(origin, displacement);

       biTriTemp= englishText(text);

     } else {

       text= decryptCaesar(origin, displacement);

       biTriTemp= germanText(text);

     }


     /* displacement causing highest biTri value is key */

     if ( biTriMax< biTriTemp ) 

       {

         biTriMax= biTriTemp;

         key= displacement;

       }

   }


   System.out.println("Schluessel lautet: "+ key );

   return key;

  }


  public static String encryptCaesar( String text, int key ) {
    return modifyText(text, key);
  }

  public static String decryptCaesar( String text, int key ) {
    key*= -1;
    return modifyText(text, key);
  }


  public static String modifyText( String text, int key ) {
    String encrypted= "";
  
    key%= 26;

    for ( int i= 0; i< text.length(); i++ ) {

      int currentChar= (int) text.charAt(i);
      int code= currentChar;

      /*lower case letters*/
      code= filterSigns(currentChar, code, key, 97, 122);

      /* upper case letters */
      code= filterSigns(currentChar, code, key, 65, 90);

      /* numbers */      
      code= filterSigns(currentChar, code, key, 48, 57);

      encrypted+= (char) code; 
    }

    return encrypted;
  }

  /*replaces char only if it is situated in given boundarys*/
  public static int filterSigns(int currentChar, int code, int key,
                             int lowerBoundary, int upperBoundary ) {

    int range= upperBoundary - lowerBoundary + 1;

    if ( (currentChar >= lowerBoundary) & 
         (currentChar <= upperBoundary)   ) {

        code= currentChar + key;

        while ( code > upperBoundary ) {

          code-= range;

        }

        while( code < lowerBoundary ) {

          code+= range;

        }        
      }

    return code;
  } 

}