Cäsar-Verschlüsselung

Cäsar-Verschlüsselung #

Falls du noch nicht mit der Cäsar-Verschlüsselung vertraut bist, sieh’ dir zuerst die Seiten dazu auf Wikipedia an.

Aufgabe #

Ergänze die Methode verschluessele in der Klasse Caesar. Die Datei beinhaltet einen Test – lass ihn regelmäßig laufen und überprüfe, ob deine Implementierung funktioniert. Verwende bei Bedarf die beiden in der Klasse enthaltenen Methoden positionImAlphabet und buchstabeAnPosition.

class Caesar {

   static String verschluessele(String text, int verschiebung) {
      String verschluesselt = "";
      // Hier kommt dein Code hin:


      return verschluesselt;
   }

   /**
    * Die Methode positionImAlphabet gibt für einzelne
    * Buchstaben deren Position (1..26) im Alphabet zurück.
    * Für Umlaute, andere Zeichen und längere Zeichenketten
    * wird -1 zurückgegeben.
    */
   static int positionImAlphabet(String zeichen) {
      int verschluesselt = -1;
      if(zeichen.length() == 1) {
         String alphabet = "abcdefghijklmnopqrstuvwxyz";
         verschluesselt = alphabet.indexOf(zeichen.toLowerCase());
         if(verschluesselt != -1) {
            verschluesselt++;
         }
      }
      return verschluesselt;
   }

   /**
    * Die Methode buchstabeAnPosition gibt für Zahlen zwischen
    * 1 und 26 Buchstaben zurück, die an der entsprechenden
    * Position im Alphabet stehen. Für alle anderen Zahlen
    * wird eine leere Zeichenkette zurückgegeben.
    */
   static String buchstabeAnPosition(int position) {
      String buchstabe = "";
      String alphabet = "abcdefghijklmnopqrstuvwxyz";
      if(position > 0 && position < 27) {
         buchstabe += alphabet.substring(position - 1, position);
      }
      return buchstabe;
   }

   static void teste() {
      // Getestet wird immer mit Verschiebung von 3
      int verschiebung = 3;
      String[][] testfälle = new String[4][2];
      testfälle[0][0] = "abc";
      testfälle[0][1] = "def";
      testfälle[1][0] = "Hallo";
      testfälle[1][1] = "kdoor";
      testfälle[2][0] = "xyz";
      testfälle[2][1] = "abc";
      testfälle[3][0] = "Mister X, das wird nichts!";
      testfälle[3][1] = "plvwhu a, gdv zlug qlfkwv!";

      boolean alleTestsBestanden = true;
      for (String[] testfall : testfälle) {
         String ergebnis = verschluessele(testfall[0], verschiebung);
         if(ergebnis.equals(testfall[1])) {
            println("+", "green");
         } else {
            println("Test fehlgeschlagen", "red");
            println("Testfall: " + testfall[0]);
            println("Erwartet wurde:");
            println(testfall[1]);
            println("Erhalten:");
            println(ergebnis);
            alleTestsBestanden = false;
         }
      }
      println(alleTestsBestanden ? "Alle Tests bestanden!" : "Einige Tests wurden nicht bestanden.");
   }
   
}

Caesar.teste();

Ergänze die Funktion verschluessele . Die Datei beinhaltet Tests – lass sie regelmäßig laufen und überprüfe, ob deine Implementierung funktioniert. Verwende bei Bedarf die beiden in der Klasse enthaltenen Methoden position_im_alphabet und buchstabe_an_position.

import doctest

alphabet = 'abcdefghijklmnopqrstuvwxyz'

def verschluessele(text: str, verschiebung: int) -> str:
    """
    Nimmt Texte (Zeichenketten) und eine Verschiebung entgegen und gibt
    entsprechend verschlüsselte Texte zurück. Die Texte werden in Kleinbuchstaben
    ausgeben, Leerzeichen und Satzzeichen bleiben erhalten.
    
    >>> verschluessele('abc', 3)
    'def'
    >>> verschluessele('Hallo', 1)
    'ibmmp'
    >>> verschluessele('xyz', 3)
    'abc'
    >>> verschluessele('Mister X, das wird nichts!', 3)
    'plvwhu a, gdv zlug qlfkwv!'
    >>> verschluessele('plvwhu a, gdv zlug qlfkwv!', 23)
    mister x, das wird nichts!
    """

    # Ersetze pass durch deinen Code
    pass

def position_im_alphabet(zeichen: str) -> int:
    """
    Die Funktion positionImAlphabet gibt für einzelne
    Buchstaben deren Position (1..26) im Alphabet zurück.
    Für Umlaute, andere Zeichen und längere Zeichenketten
    wird -1 zurückgegeben.
    
    >>> position_im_alphabet('c')
    3
    >>> position_im_alphabet('Z')
    26
    >>> position_im_alphabet(' ')
    -1
    >>> position_im_alphabet('abc')
    -1
    """
    verschluesselt = -1
    if len(zeichen) == 1 and zeichen.lower() in alphabet:
        verschluesselt = alphabet.index(zeichen.lower()) + 1 
    return verschluesselt;

def buchstabe_an_position(position: int) -> str:
    """
    Die Funktion buchstabe_an_position gibt für Zahlen zwischen
    1 und 26 Buchstaben zurück, die an der entsprechenden
    Position im Alphabet stehen. Für alle anderen Zahlen
    wird eine leere Zeichenkette zurückgegeben.
    
    >>> buchstabe_an_position(2)
    'b'
    >>> buchstabe_an_position(25)
    'y'
    >>> buchstabe_an_position(27)
    ''
    >>> buchstabe_an_position(-1)
    ''
    """
    if 0 < position < 27:
        return alphabet[position - 1]
    return ''
        
if __name__ == '__main__':
    doctest.testmod()

Lege die beiden Klassen Caesar und CaesarTest in je eigenen Dateien in einem Verzeichnis an. (Lass dir ggf. von deiner IDE helfen, die Abhängigkeiten für die Verwendung von Junit aufzulösen.)

Ergänze die Methode verschluessele in der Klasse Caesar. Lass den Test regelmäßig laufen und überprüfe, ob deine Implementierung funktioniert.

Verwende bei Bedarf die beiden in der Klasse enthaltenen Methoden positionImAlphabet und buchstabeAnPosition. Die Klasse enthält eine Methode println, die die Methode System.out.println ersetzt.

Datei Caesar.java:

class Caesar {

   static String verschluessele(String text, int verschiebung) {
      StringBuilder verschlusselterText = new StringBuilder();
      // Hier kommt dein Code hin:



      return verschlusselterText.toString();
   }

   /**
    * Die Methode positionImAlphabet gibt für einzelne
    * Buchstaben deren Position (1..26) im Alphabet zurück.
    * Für Umlaute, andere Zeichen und längere Zeichenketten
    * wird -1 zurückgegeben.
    */
   static int positionImAlphabet(String zeichen) {
      int verschluesselt = -1;
      if(zeichen.length() == 1) {
         String alphabet = "abcdefghijklmnopqrstuvwxyz";
         verschluesselt = alphabet.indexOf(zeichen.toLowerCase());
         if(verschluesselt != -1) {
            verschluesselt++;
         }
      }
      return verschluesselt;
   }

   /**
    * Die Methode buchstabeAnPosition gibt für Zahlen zwischen
    * 1 und 26 Buchstaben zurück, die an der entsprechenden
    * Position im Alphabet stehen. Für alle anderen Zahlen
    * wird eine leere Zeichenkette zurückgegeben.
    */
   static String buchstabeAnPosition(int position) {
      String buchstabe = "";
      String alphabet = "abcdefghijklmnopqrstuvwxyz";
      if(position > 0 && position < 27) {
         buchstabe += alphabet.substring(position - 1, position);
      }
      return buchstabe;
   }

   static void println(Object o) {
       System.out.println(o.toString());
   }
}

Datei CaesarTest.java:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class CaesarTest {

    @Test
    void testVerschluessele() {
        assertEquals("def", Caesar.verschluessele("abc", 3));
        assertEquals("ibmmp", Caesar.verschluessele("Hallo", 1));
        assertEquals("abc", Caesar.verschluessele("xyz", 3));
        assertEquals("plvwhu a, gdv zlug qlfkwv!", Caesar.verschluessele("Mister X, das wird nichts!", 3));
        assertEquals("mister x, das wird nichts!", Caesar.verschluessele("plvwhu a, gdv zlug qlfkwv!", 23));
    }

    @Test
    void testPositionImAlphabet() {
        assertEquals(3, Caesar.positionImAlphabet("c"));
        assertEquals(26, Caesar.positionImAlphabet("Z"));
        assertEquals(-1, Caesar.positionImAlphabet(" "));
        assertEquals(-1, Caesar.positionImAlphabet("abc"));
    }

    @Test
    void testBuchstabeAnPosition() {
        assertEquals("b", Caesar.buchstabeAnPosition(2));
        assertEquals("y", Caesar.buchstabeAnPosition(25));
        assertEquals("", Caesar.buchstabeAnPosition(27));
        assertEquals("", Caesar.buchstabeAnPosition(-1));
    }
}

Tipps für Online-IDE Java #

Tipp 1

Nutze eine for-Wiederholung, um jeden Buchstaben des Eingabetextes durchzugehen. Lege vor dem Wiederholungsblock eine Variable verschluesselterText (oder ähnlich) an, die im Wiederholungsblock nach und nach ergänzt wird.

So initialisiert du die Variable gleich mit einer leeren Zeichenkette:

String verschlusselterText = "";
Tipp 2

Eine vereinfachte for-Wiederholung benötigt z.B. ein Array, um darüber zu iterieren (jedes Element einmal aufzurufen.) Um die übergebene Zeichenkette in ein Array zu verwandeln, in dem jeder Buchstabe einzeln (wieder als Zeichenkette) enthalten ist, kannst du die split-Methode nutzen:

String[] textArray = text.split("");
Tipp 3

Um jedes Zeichen der Reihe nach einmal aufzurufen, kannst du die vereinfachte for-Wiederholung nutzen:

for (String zeichen : textArray) {
    // Hier wandelst du jedes einzelne Zeichen um
    // und hängst es an die vorbereitete Variable
    // verschluesselterText
}
Tipp 4

Die Methode positionImAlphabet liefert dir die Position des Zeichens im Alphabet zurück, oder -1, falls du keinen Buchstaben (oder einen Umlaut o.ä.) übergibst. Es bietet sich eine Fallunterscheidung an, die sonstige Zeichen unverändert übernimmt:

int position = positionImAlphabet(zeichen);
if(position != -1) {
    // Hier muss das Zeichen verschlüsselt werden und
    // an verschluesselterText gehängt werden.

} else {
    // Falls das Zeichen kein Buchstabe ist,
    // wird es einfach so angehängt
    verschluesselterText += zeichen;
}
Tipp 5

Wie verschlüsseln wir nun Zeichen?

Ersteinmal könntest du ausprobieren, die Verschiebung zur Position einfach hinzuzuzählen. Aus der errechneten Position erzeugen wir mit buchstabeAnPosition wieder Buchstaben:

int positionVerschluesselt = position + verschiebung;
verschluesselterText += buchstabeAnPosition(positionVerschluesselt);

Einige Tests werden noch fehlschlagen…

Tipp 6

Soll erfolgreich über den Buchstaben z hinaus verschoben werden, hilft die Modulo-Operation (%), die den Rest berechnet. Weil unsere Methode positionImAlphabet Positionen zwischen 1 und 26 zurückgibt (und nicht zwischen 0 und 25), müssen wir ein wenig hin- und herrechnen:

int positionVerschluesselt = ((position - 1 + verschiebung) % 26) + 1;
verschluesselterText += buchstabeAnPosition(positionVerschluesselt);
Lösungsvorschlag
static String verschluessele(String text, int verschiebung) {
  String verschluesselterText = "";
  String[] textArray = text.split("");
  for (String zeichen : textArray) {
     int position = positionImAlphabet(zeichen);
     if(position != -1) {
        int positionVerschluesselt = ((position - 1 + verschiebung) % 26) + 1;
        verschluesselterText += buchstabeAnPosition(positionVerschluesselt);
     } else {
        verschluesselterText += zeichen;
     }
  }
  return verschluesselterText;
}

Tipps für Python #

Tipp 1

Nutze eine for-Wiederholung, um jeden Buchstaben des Eingabetextes durchzugehen. Lege vor dem Wiederholungsblock eine Variable text_verschluesselt (oder ähnlich) an, die im Wiederholungsblock nach und nach ergänzt wird.

So initialisiert du die Variable gleich mit einer leeren Zeichenkette:

text_verschluesselt = ''
Tipp 2

Um jedes Zeichen der Reihe nach einmal aufzurufen, kannst du eine for-Wiederholung nutzen:

for zeichen in text:
    # Hier wandelst du jedes einzelne Zeichen um
    # und hängst es an die vorbereitete Variable
    # text_verschluesselt
Tipp 3

Die Funktion position_im_alphabet liefert dir die Position des Zeichens im Alphabet zurück, oder -1, falls du keinen Buchstaben (oder einen Umlaut o.ä.) übergibst. Es bietet sich eine Fallunterscheidung an, die sonstige Zeichen unverändert übernimmt:

vielleicht_position = position_im_alphabet(zeichen)
if not vielleicht_position == -1:
    # Hier muss das Zeichen verschlüsselt werden und
    # an text_verschluesselt gehängt werden.

else:
    # Falls das Zeichen kein Buchstabe ist,
    # wird es einfach so angehängt
    text_verschluesselt += zeichen
Tipp 4

Wie verschlüsseln wir nun Zeichen?

Ersteinmal könntest du ausprobieren, die Verschiebung zur Position einfach hinzuzuzählen. Aus der errechneten Position erzeugen wir mit buchstabe_an_position wieder Buchstaben:

position_verschluesselt = vielleicht_position + verschiebung
verschluesselt += buchstabe_an_position(position_verschluesselt)

Einige Tests werden noch fehlschlagen…

Tipp 5

Soll erfolgreich über den Buchstaben z hinaus verschoben werden, hilft die Modulo-Operation (%), die den Rest berechnet. Weil unsere Methode position_im_alphabet Positionen zwischen 1 und 26 zurückgibt (und nicht zwischen 0 und 25), müssen wir ein wenig hin- und herrechnen:

position_verschluesselt = ((vielleicht_position - 1 + verschiebung) % 26) + 1
zeichen_verschluesselt = buchstabe_an_position(position_verschluesselt)
text_verschluesselt += zeichen_verschluesselt
Lösungsvorschlag
def verschluessele(text: str, verschiebung: int) -> str:
    """
    Nimmt Texte (Zeichenketten) und eine Verschiebung entgegen und gibt
    entsprechend verschlüsselte Texte zurück. Die Texte werden in Kleinbuchstaben
    ausgeben, Leerzeichen und Satzzeichen bleiben erhalten.
    
    >>> verschluessele('abc', 3)
    'def'
    >>> verschluessele('Hallo', 1)
    'ibmmp'
    >>> verschluessele('xyz', 3)
    'abc'
    >>> verschluessele('Mister X, das wird nichts!', 3)
    'plvwhu a, gdv zlug qlfkwv!'
    """
    text_verschluesselt = ''
    for zeichen in text:
        vielleicht_position = position_im_alphabet(zeichen)
        if not vielleicht_position == -1:
            position_verschluesselt = ((vielleicht_position - 1 + verschiebung) % 26) + 1
            zeichen_verschluesselt = buchstabe_an_position(position_verschluesselt)
            text_verschluesselt += zeichen_verschluesselt
        else:
            text_verschluesselt += zeichen
    return text_verschluesselt

Tipps für Java #

Tipp 1

Nutze eine for-Wiederholung, um jeden Buchstaben des Eingabetextes durchzugehen.

Um zum Schluss den verschlüsselten Text als Zeichenkette zurückzugeben, ist bereits ein StringBuilder-Objekt verschluesselterText angelegt. Mit der Methode append lassen sich dem StringBuilder-Objekt etwas anhängen:

verschlusselterText.append("Ich bin eine Zeichenkette");
Tipp 2

Eine vereinfachte for-Wiederholung benötigt z.B. ein Array, um darüber zu iterieren (jedes Element einmal aufzurufen.) Um die übergebene Zeichenkette in ein Array zu verwandeln, in dem jeder Buchstabe einzeln (wieder als Zeichenkette) enthalten ist, kannst du die split-Methode nutzen:

String[] textArray = text.split("");
Tipp 3

Um jedes Zeichen der Reihe nach einmal aufzurufen, kannst du die vereinfachte for-Wiederholung nutzen:

for (String zeichen : textArray) {
    // Hier wandelst du jedes einzelne Zeichen um
    // und hängst es an die vorbereitete Variable
    // verschluesselterText
}
Tipp 4

Die Methode positionImAlphabet liefert dir die Position des Zeichens im Alphabet zurück, oder -1, falls du keinen Buchstaben (oder einen Umlaut o.ä.) übergibst. Es bietet sich eine Fallunterscheidung an, die sonstige Zeichen unverändert übernimmt:

int position = positionImAlphabet(zeichen);
if(position != -1) {
    // Hier muss das Zeichen verschlüsselt werden und
    // an verschluesselterText gehängt werden.

} else {
    // Falls das Zeichen kein Buchstabe ist,
    // wird es einfach so angehängt
    verschluesselterText.append(zeichen);
}
Tipp 5

Wie verschlüsseln wir nun Zeichen?

Ersteinmal könntest du ausprobieren, die Verschiebung zur Position einfach hinzuzuzählen. Aus der errechneten Position erzeugen wir mit buchstabeAnPosition wieder Buchstaben:

int positionVerschluesselt = position + verschiebung;
verschluesselterText.append(buchstabeAnPosition(positionVerschluesselt));

Einige Tests werden noch fehlschlagen…

Tipp 6

Soll erfolgreich über den Buchstaben z hinaus verschoben werden, hilft die Modulo-Operation (%), die den Rest berechnet. Weil unsere Methode positionImAlphabet Positionen zwischen 1 und 26 zurückgibt (und nicht zwischen 0 und 25), müssen wir ein wenig hin- und herrechnen:

int positionVerschluesselt = ((position - 1 + verschiebung) % 26) + 1;
verschluesselterText.append(buchstabeAnPosition(positionVerschluesselt));
Lösungsvorschlag
static String verschluessele(String text, int verschiebung) {
  StringBuilder verschluesselterText = new StringBuilder();
  String[] textArray = text.split("");
  for (String zeichen : textArray) {
     int position = positionImAlphabet(zeichen);
     if(position != -1) {
        int positionVerschluesselt = ((position - 1 + verschiebung) % 26) + 1;
        verschluesselterText.append(buchstabeAnPosition(positionVerschluesselt));
     } else {
        verschluesselterText.append(zeichen);
     }
  }
  return verschluesselterText.toString();
}