Caesar Cipher

March 11, 2014

I was asked about a caesar cipher the other day, and suggested that my questioner search for caesar cipher here at Programming Praxis. To my surprise, I discovered that we have never done a caesar cipher (we did the ROT13 cipher, but not a general-purpose caesar cipher), so I apologized to my friend and wrote today’s exercise.

A caeser cipher, named after Julius Caesar, who either invented the cipher or was an early user of it, is a simple substitution cipher in which letters are substituted at a fixed distance along the alphabet, which cycles; children’s magic decoder rings implement a caesar cipher. Non-alphabetic characters are passed unchanged. For instance, the plaintext PROGRAMMINGPRAXIS is rendered as the ciphertext SURJUDPPLQJSUDALV with a shift of 3 positions.

Your task is to write functions that encipher and decipher text using a caesar cipher. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

9 Responses to “Caesar Cipher”

  1. ritesh bhatia said

    What should be the cipher key ?

  2. 3coma3 said

    the key is the shift distance

  3. Daniel said

    Here’s a solution in Julia. There’s also a one-liner, encipherOneLiner.

    function encipher(s, key)
        function shift(c)
            if isalpha(c)
                char(mod((int(uppercase(c)) - 65 + key), 26) + 65)
            else
                c
            end
        end
        map(shift, s)
    end
    
    function decipher(s, key)
        encipher(s,-key)
    end
    
    function encipherOneLiner(s, key)
        map(c->isalpha(c)?char(mod((int(uppercase(c))-65+key),26)+65):c,s)
    end
    
  4. Graham said

    The Caesar cipher shows up in Graham Hutton’s *great* book on Haskell.
    Here’s a version similar to @Daniel’s:

    import Data.Char (chr, isAsciiUpper, ord)

    shift :: Int -> Char -> Char
    shift n c | isAsciiUpper c = chr $ a + ((n + (ord c – a) `mod` 26))
    | otherwise = c
    where
    a = ord ‘A’

    caesar :: Int -> String -> String
    caesar n = map $ shift n

    main :: IO ()
    main = mapM_ putStrLn [p, c, p’]
    where
    p = "PROGRAMMING PRAXIS"
    c = caesar 3 p
    p’ = caesar (-3) c

  5. Graham said

    Apologies for the crap formatting. Apparently I’m really out of practice!

  6. JP said

    Racket / Rackjure

    (define (caesar str n)
      (define A (char->integer #\A))
      (define a (char->integer #\a))
      (list->string
       (for/list ([c (in-string str)])
         (cond
           [(char<=? #\A c #\Z)
            (~> c char->integer (- A) (+ n) (mod 26) (+ A) integer->char)]
           [(char<=? #\a c #\z)
            (~> c char->integer (- a) (+ n) (mod 26) (+ a) integer->char)]
           [else
            c]))))
    

    Full writeup: jverkamp.com

  7. Mike said

    python solution:

    class SubstitutionCypher:
    	def __init__(self, mapping):
    		self.encode_map = mapping
    		self.decode_map = {v:k for k,v in mapping.items()}
    
    	def encode(self, cleartext):
    		return cleartext.translate(self.encode_map)
    
    	def decode(self, cyphertext):
    		return cyphertext.translate(self.decode_map)
    
    class CaesarCypher(SubstitutionCypher):
    	from string import ascii_uppercase
    	
    	def __init__(self, key, alphabet=ascii_uppercase):
    		key %= len(alphabet)
    		shifted = alphabet[key:] + alphabet[:key]
    		super().__init__(str.maketrans(alphabet, shifted))
    
    CaesarCypher(3).encode('PROGRAMMING PRAXIS')    # => SURJUDPPLQJ SUDALV
    
    CaesarCypher(-3).encode('SURJUDPPLQJ SUDALV')    # => PROGRAMMING PRAXIS
    
    

    To bring the cypher up to the current century, we can use an alphabet containing all the uppercase Unicode characters.

    
    import unicodedata as ud
    
    alphabet = ''.join(c for c in map(chr, range(0x10FFFF)) if c.isupper())
    
    CaesarCypher(432, alphabet=alphabet).encode('PROGRAMMING PRAXIS')    # => ՇՉՆԾՉԸՄՄՀՅԾ ՇՉԸՏՀՊ
    
    CaesarCypher(-432, alphabet=alphabet).encode('ՇՉՆԾՉԸՄՄՀՅԾ ՇՉԸՏՀՊ')    # => PROGRAMMING PRAXIS
    
    
  8. shlomy said

    {code}
    def CeaserC(word,offset=1):
    #final=[chr(ord(i)+offset) for i in word]
    return (”.join([chr(ord(i)+offset) for i in word]))

    def Ceaserback(word,offset=1):
    #final=[chr(ord(i)-offset) for i in word]
    return (”.join([chr(ord(i)-offset) for i in word]))

    print (CeaserC(“thisisatest”,1))
    print (Ceaserback(“uijtjtbuftu”))
    {/code}

  9. Here’s a Java solution:

    import java.util.HashMap;
    
    public class CaesarCipher {
    
      private static final char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    
      private HashMap<Character, Character> cryptTable;
      private HashMap<Character, Character> decryptTable;
    
      public CaesarCipher(final int shift) {
        this.cryptTable = buildTranslationTable(ALPHABET, shift);
        this.decryptTable = buildTranslationTable(ALPHABET, -shift);
      }
    
      public String crypt(final String plainText) {
        return translate(this.cryptTable, plainText);
      }
    
      public String decrypt(final String encryptedText) {
        return translate(this.decryptTable, encryptedText);
      }
    
      private HashMap<Character, Character> buildTranslationTable(final char[] alphabet, final int shift) {
        HashMap<Character, Character> translationTable = new HashMap<>(alphabet.length);
        for (int i = 0; i < alphabet.length; i++) {
          Character plain = alphabet[i];
          Character translated = alphabet[mod((i + shift), alphabet.length)];
          translationTable.put(plain, translated);
        }
        return translationTable;
      }
    
      private String translate(final HashMap<Character, Character> translationTable, final String text) {
        StringBuilder translatedText = new StringBuilder(text.length());
        for (int i = 0; i < text.length(); i++) {
          Character plain = text.charAt(i);
          Character translated = translationTable.get(plain);
          if (translated != null) {
            translatedText.append(translated);
          } else {
            translatedText.append(plain);
          }
        }
        return translatedText.toString();
      }
    
      private int mod(int a, int b) {
        int r = a % b;
        if (r < 0) { r += b; }
        return r;
      }
    
      public static void main(String[] args) {
        CaesarCipher cipher = new CaesarCipher(3);
        System.out.println(cipher.crypt("PROGRAMMINGPRAXIS"));    // -> SURJUDPPLQJSUDALV
        System.out.println(cipher.decrypt("SURJUDPPLQJSUDALV")); // -> PROGRAMMINGPRAXIS
      }
    }
    

Leave a comment