Caesar cipher

From Rosetta Code
Revision as of 02:00, 19 September 2011 by rosettacode>Crazyfirex (→‎{{header|AutoHotkey}}: golfed the golf)
Task
Caesar cipher
You are encouraged to solve this task according to the task description, using any language you may know.

Implement a Caesar cipher, both encryption and decryption. The key is an integer from 1 to 25. This cipher rotates the letters of the alphabet (A to Z). The encryption replaces each letter with the 1st to 25th next letter in the alphabet (wrapping Z to A). So key 2 encrypts "HI" to "JK", but key 20 encrypts "HI" to "BC". This simple "monoalphabetic substitution cipher" provides almost no security, because an attacker who has the encrypted message can either use frequency analysis to guess the key, or just try all 25 keys.

Caesar cipher is identical to Vigenère cipher with key of length 1. Also, Rot-13 is identical to Caesar cipher with key 13.

Ada

<lang Ada>with Ada.Text_IO;

procedure Caesar is

  type M26 is mod 26;
  function To_M26(C: Character; Offset: Character) return M26 is
  begin
     return M26(Character'Pos(C)-Character'Pos(Offset));
  end To_M26;
  function To_Character(Value:   in  M26; Offset: Character)
                       return Character is
  begin
     return Character'Val(Integer(Value)+Character'Pos(Offset));
  end To_Character;
  function Encrypt (Plain: String; Key: M26) return String is
     Ciph: String(Plain'Range);
  begin
     for I in Plain'Range loop
        case Plain(I) is
           when 'A' .. 'Z' =>
              Ciph(I) := To_Character(To_M26(Plain(I), 'A')+Key, 'A');
           when 'a' .. 'z' =>
              Ciph(I) := To_Character(To_M26(Plain(I), 'a')+Key, 'a');
           when others =>
              Ciph(I) := Plain(I);
        end case;
     end loop;
     return Ciph;
  end Encrypt;
  Text:  String := Ada.Text_IO.Get_Line;
  Key: M26 := 3; -- Default key from "Commentarii de Bello Gallico"

begin -- Caesar main program

  Ada.Text_IO.Put_Line("Plaintext ------------>" & Text);
  Text := Encrypt(Text, Key);
  Ada.Text_IO.Put_Line("Ciphertext ----------->" & Text);
  Ada.Text_IO.Put_Line("Decrypted Ciphertext ->" & Encrypt(Text, -Key));

end Caesar;</lang> Output

> ./caesar 
The five boxing wizards jump quickly
Plaintext ------------>The five boxing wizards jump quickly
Ciphertext ----------->Wkh ilyh eralqj zlcdugv mxps txlfnob
Decrypted Ciphertext ->The five boxing wizards jump quickly

ALGOL 68

Translation of: Ada

Note: This specimen retains the original Ada coding style.

Works with: ALGOL 68 version Revision 1 - no extensions to language used.
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.

<lang algol68>#!/usr/local/bin/a68g --script #

program caesar: BEGIN

  MODE MODXXVI = SHORT SHORT INT; # MOD26 #
  PROC to m26 = (CHAR c, offset)MODXXVI:
  BEGIN
     ABS c - ABS offset
  END #to m26#;
  PROC to char = (MODXXVI value, CHAR offset)CHAR:
  BEGIN
     REPR ( ABS offset + value MOD 26 )
  END #to char#;
  PROC encrypt = (STRING plain, MODXXVI key)STRING:
  BEGIN
     [UPB plain]CHAR ciph;
     FOR i TO UPB plain DO
        CHAR c = plain[i];
        ciph[i]:=
          IF "A" <= c AND c <= "Z" THEN
              to char(to m26(c, "A")+key, "A")
          ELIF "a" <= c AND c <= "z" THEN
              to char(to m26(c, "a")+key, "a")
          ELSE
              c
          FI
     OD;
     ciph
  END #encrypt#;
  1. caesar main program #
  STRING text := "The five boxing wizards jump quickly" # OR read string #;
  MODXXVI key := 3; # Default key from "Bello Gallico" #
  printf(($gl$, "Plaintext ------------>" + text));
  text := encrypt(text, key);
  printf(($gl$, "Ciphertext ----------->" + text));
  printf(($gl$, "Decrypted Ciphertext ->" + encrypt(text, -key)))

END #caesar#</lang> Output:

Plaintext ------------>The five boxing wizards jump quickly
Ciphertext ----------->Wkh ilyh eralqj zlcdugv mxps txlfnob
Decrypted Ciphertext ->The five boxing wizards jump quickly

AutoHotkey

This ungodly solution is an attempt at code-golf. It requires input to be all-caps alphabetic ASCII, and might not run on x64 <lang AutoHotkey>n=2 s=HI t:=&s While *t o.=Chr(Mod(*t-65+n,26)+65),t+=2 MsgBox % o</lang> This next one is much more sane and handles input very well, including case. <lang AutoHotkey>Caesar(string, n){ Loop Parse, string { If (Asc(A_LoopField) >= Asc("A") and Asc(A_LoopField) <= Asc("Z")) out .= Chr(Mod(Asc(A_LoopField)-Asc("A")+n,26)+Asc("A")) Else If (Asc(A_LoopField) >= Asc("a") and Asc(A_LoopField) <= Asc("z")) out .= Chr(Mod(Asc(A_LoopField)-Asc("a")+n,26)+Asc("a")) Else out .= A_LoopField } return out }

MsgBox % Caesar("h i", 2) "`n" Caesar("Hi", 20)</lang>

It outputs

j k
Bc

C

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <string.h>
  1. define caesar(x) rot(13, x)
  2. define decaesar(x) rot(13, x)
  3. define decrypt_rot(x, y) rot((26-x), y)

void rot(int c, char *str) { int l = strlen(str); char alpha[2][27] = { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"};

int i; for (i = 0; i < l; i++) { if (!isalpha(str[i]) || (str[i] == ' ')) continue;

str[i] = alpha[isupper(str[i])][((int)(tolower(str[i])-'a')+c)%26]; } }


int main() { char str[100] = "This is a top secret text message!";

printf("Original: %s\n", str); caesar(str); printf("Encrypted: %s\n", str); decaesar(str); printf("Decrypted: %s\n", str);

return 0; }</lang>

D

<lang d>import std.stdio, std.traits, std.ctype, std.conv;

S rot(S)(S s, int key) if (isSomeString!S) {

   dchar[] r = new dchar[s.length];
       
   foreach (i, dchar c; s) {
       if (islower(c)) 
           c = ((c - 'a' + key) % 26 + 'a');
       else if (isupper(c)) 
           c = ((c - 'A' + key) % 26 + 'A');
       r[i] = c;      
   }
   return to!S(r);

}

void main() {

   int key = 3;
   auto txt = "The five boxing wizards jump quickly";
   writeln("Original:  ", txt);
   writeln("Encrypted: ", txt.rot(key));
   writeln("Decrypted: ", txt.rot(key).rot(26-key));

}</lang>

Original:  The five boxing wizards jump quickly
Encrypted: Wkh ilyh eralqj zlcdugv mxps txlfnob
Decrypted: The five boxing wizards jump quickly

Simpler in-place version (same output): <lang d>import std.stdio, std.ctype;

void inplaceRot(char[] txt, in int key) {

   foreach (ref c; txt) {
       if (islower(c))
           c = cast(char)((c - 'a' + key) % 26 + 'a');
       else if (isupper(c))
           c = cast(char)((c - 'A' + key) % 26 + 'A');
   }

}

void main() {

   enum key = 3;
   auto txt = "The five boxing wizards jump quickly".dup;
   writeln("Original:  ", txt);
   txt.inplaceRot(key);
   writeln("Encrypted: ", txt);
   txt.inplaceRot(26 - key);
   writeln("Decrypted: ", txt);

}</lang>

F#

<lang fsharp>open System

module caesar =

   let cipher (k:int) (m:string) =
       m.ToUpper().ToCharArray()
       |> Array.filter Char.IsLetter
       |> Array.map int
       |> Array.map (fun c -> ((c - 65 + k) % 26 + 65) |> char)
       |> (fun s -> new string(s))
   let encrypt k = cipher k
   let decrypt k = cipher (26 - k)

</lang>

> caesar.encrypt 2 HI
JK
> caesar.encrypt 20 HI
BC
> let c = caesar.encrypt 13 "The quick brown fox jumps over the lazy dog."
val c : string = "GURDHVPXOEBJASBKWHZCFBIREGURYNMLQBT"
> caesar.decrypt 13 c
val it : string = "THEQUICKBROWNFOXJUMPSOVERTHELAZYDOG"

Fortran

<lang fortran>program Caesar_Cipher

 implicit none
 integer, parameter :: key = 3     
 character(43) :: message = "The five boxing wizards jump quickly"
 write(*, "(2a)") "Original message  = ", message
 call encrypt(message)
 write(*, "(2a)") "Encrypted message = ", message
 call decrypt(message)
 write(*, "(2a)") "Decrypted message = ", message
 

contains

subroutine encrypt(text)

 character(*), intent(inout) :: text
 integer :: i
 
 do i = 1, len(text)
   select case(text(i:i))
     case ('A':'Z')
       text(i:i) = achar(modulo(iachar(text(i:i)) - 65 + key, 26) + 65)
     case ('a':'z')
       text(i:i) = achar(modulo(iachar(text(i:i)) - 97 + key, 26) + 97)
   end select
 end do

end subroutine

subroutine decrypt(text)

 character(*), intent(inout) :: text
 integer :: i
 
 do i = 1, len(text)
   select case(text(i:i))
     case ('A':'Z')
       text(i:i) = achar(modulo(iachar(text(i:i)) - 65 - key, 26) + 65)
     case ('a':'z')
       text(i:i) = achar(modulo(iachar(text(i:i)) - 97 - key, 26) + 97)
   end select
 end do

end subroutine

end program Caesar_Cipher</lang> Output

Original message  = The five boxing wizards jump quickly
Encrypted message = Wkh ilyh eralgj zlcdugv mxps txlfnob
Decrypted message = The five boxing wizards jump quickly

GAP

<lang gap>CaesarCipher := function(s, n) local r, c, i, lower, upper; lower := "abcdefghijklmnopqrstuvwxyz"; upper := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; r := ""; for c in s do i := Position(lower, c); if i <> fail then Add(r, lower[RemInt(i + n - 1, 26) + 1]); else i := Position(upper, c); if i <> fail then Add(r, upper[RemInt(i + n - 1, 26) + 1]); else Add(r, c); fi; fi; od; return r; end;

CaesarCipher("IBM", 25);

  1. "HAL"

CaesarCipher("Vgg cphvi wzdibn vmz wjmi amzz viy zlpvg di ydbidot viy mdbcon.", 5);

  1. "All human beings are born free and equal in dignity and rights."</lang>

Go

<lang go>package main

import (

   "fmt"
   "strings"

)

type ckey struct {

   enc, dec func(int) int

}

func newCaesar(k int) (*ckey, bool) {

   if k < 1 || k > 25 {
       return nil, false
   }
   return &ckey{
       enc: func(c int) int {
           if c >= 'a' && c <= 'z'-k || c >= 'A' && c <= 'Z'-k {
               return c + k
           } else if c > 'z'-k && c <= 'z' || c > 'Z'-k && c <= 'Z' {
               return c + k - 26
           }
           return c
       },
       dec: func(c int) int {
           if c >= 'a'+k && c <= 'z' || c >= 'A'+k && c <= 'Z' {
               return c - k
           } else if c >= 'a' && c < 'a'+k || c >= 'A' && c < 'A'+k {
               return c - k + 26
           }
           return c
       },
   }, true

}

func (ck ckey) encipher(pt string) string {

   return strings.Map(ck.enc, pt)

}

func (ck ckey) decipher(ct string) string {

   return strings.Map(ck.dec, ct)

}

func main() {

   pt := "The five boxing wizards jump quickly"
   fmt.Println("Plaintext:", pt)
   for _, key := range []int{0, 1, 7, 25, 26} {
       ck, ok := newCaesar(key)
       if !ok {
           fmt.Println("Key", key, "invalid")
           continue
       }
       ct := ck.encipher(pt)
       fmt.Println("Key", key)
       fmt.Println("  Enciphered:", ct)
       fmt.Println("  Deciphered:", ck.decipher(ct))
   }

}</lang> Output:

Plaintext: The five boxing wizards jump quickly
Key 0 invalid
Key 1
  Enciphered: Uif gjwf cpyjoh xjabset kvnq rvjdlmz
  Deciphered: The five boxing wizards jump quickly
Key 7
  Enciphered: Aol mpcl ivepun dpghykz qbtw xbpjrsf
  Deciphered: The five boxing wizards jump quickly
Key 25
  Enciphered: Sgd ehud anwhmf vhyzqcr itlo pthbjkx
  Deciphered: The five boxing wizards jump quickly
Key 26 invalid

Haskell

<lang haskell> import Data.Char (ord, chr)

caesar :: Int -> String -> String caesar k str = map f str

 where
   f c
     | c `elem` ['a'..'z'] = tr 'a' k c
     | c `elem` ['A'..'Z'] = tr 'A' k c
     | otherwise = c

unCaesar :: Int -> String -> String unCaesar k = caesar (-1 * k)

-- char addition tr :: Char -> Int -> Char -> Char tr base offset char = chr $ ord base + (ord char - ord base + offset) `mod` 26 </lang> And trying it out in GHCi:

*Main> caesar 1 "hal"
"ibm"
*Main> unCaesar 1 "ibm"
"hal"

Icon and Unicon

Strictly speaking a Ceasar Cipher is a shift of 3 (the default in this case). <lang Icon>procedure main() ctext := caesar(ptext := map("The quick brown fox jumped over the lazy dog")) dtext := caesar(ctext,,"decrypt") write("Plain text = ",image(ptext)) write("Encphered text = ",image(ctext)) write("Decphered text = ",image(dtext)) end

procedure caesar(text,k,mode) #: mono-alphabetic shift cipher /k := 3 k := (((k % *&lcase) + *&lcase) % *&lcase) + 1 case mode of {

 &null|"e"|"encrypt": return map(text,&lcase,(&lcase||&lcase)[k+:*&lcase])
 "d"|"decrypt"      : return map(text,(&lcase||&lcase)[k+:*&lcase],&lcase)
 }

end</lang>

Output:

Plain text  = "the quick brown fox jumped over the lazy dog"
Encphered text = "wkh txlfn eurzq ira mxpshg ryhu wkh odcb grj"
Decphered text = "the quick brown fox jumped over the lazy dog"

J

If we assume that the task also requires us to leave non-alphabetic characters alone:

<lang j>cndx=: [: , 65 97 +/ 26 | (i.26)&+ caesar=: (cndx 0)}&a.@u:@cndx@[ {~ a.i.]</lang>

Example use:<lang j> 2 caesar 'This simple "monoalphabetic substitution cipher" provides almost no security, ...' Vjku ukorng "oqpqcnrjcdgvke uwduvkvwvkqp ekrjgt" rtqxkfgu cnoquv pq ugewtkva, ...</lang>

Java

This example is incorrect. Please fix the code and remove this message.

Details: symbols are not filtered out

<lang java> public class Cipher { public static void main(String[] args) { String enc = Cipher.code( "The quick brown fox Jumped over the lazy Dog", 12); System.out.println(enc); System.out.println(Cipher.code(enc, -12));

}

public static String code(String enc, int offset) { StringBuilder encoded = new StringBuilder(); for (Character i : enc.toLowerCase().toCharArray()) { offset = offset % 26 + 26; int j = ((((int) i) - 97) + offset) % 26; if (j >= 0 && j <= 25) { encoded.append((char) (j + 97));

} } return encoded.toString(); } } </lang> Output: <lang>ftqcguowndaizrajvgybqpahqdftqxmlkpas thequickbrownfoxjumpedoverthelazydog</lang>

JavaScript

<lang javascript><html><head><title>Caesar</title></head>

<body>


<script type="application/javascript"> function disp(x) { var e = document.createTextNode(x + '\n'); document.getElementById('x').appendChild(e); }

function trans(msg, rot) { return msg.replace(/([a-z])/ig, function($1) { var c = $1.charCodeAt(0); return String.fromCharCode( c >= 97 ? (c + rot + 26 - 97) % 26 + 97 : (c + rot + 26 - 65) % 26 + 65); }); }

var msg = "The quick brown f0x Jumped over the lazy Dog 123"; var enc = trans(msg, 3); var dec = trans(enc, -3);

disp("Original:" + msg + "\nEncoded: " + enc + "\nDecoded: " + dec); </script></body></html></lang>

Liberty BASIC

<lang lb> key = 7

Print "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

'Encrypt the text Print CaesarCypher$("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", key)

'Decrypt the text by changing the key to (26 - key) Print CaesarCypher$(CaesarCypher$("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", key), (26 - key))


Function CaesarCypher$(string$, key)

   If (key < 0) Or (key > 25) Then _
   CaesarCypher$ = "Key is Ouside of Bounds" : Exit Function
   For i = 1 To Len(string$)
       rotate = Asc(Mid$(string$, i, 1))
       rotate = (rotate + key)
       If Asc(Mid$(string$, i, 1)) > Asc("Z") Then
           If rotate > Asc("z") Then rotate = (Asc("a") + (rotate - Asc("z")) - 1)
       Else
           If rotate > Asc("Z") Then rotate = (Asc("A") + (rotate - Asc("Z")) - 1)
       End If
       CaesarCypher$ = (CaesarCypher$ + Chr$(rotate))
   Next i

End Function</lang>


Mathematica

<lang Mathematica>cypher[mesg_String, n_Integer] := StringReplace[mesg,

 Join[Thread[Rule[CharacterRange["a", "z"], RotateLeft[CharacterRange["a", "z"], n]]],
  Thread[Rule[CharacterRange["A", "Z"], RotateLeft[CharacterRange["A", "Z"], n]]]]]</lang>

NetRexx

The cipher code in this sample is also used in the Rot-13 – NetRexx task. <lang NetRexx>/* NetRexx */

options replace format comments java crossref savelog symbols nobinary

messages = [ -

 'The five boxing wizards jump quickly', -
 'Attack at dawn!', -
 'HI']

keys = [1, 2, 20, 25, 13]

loop m_ = 0 to messages.length - 1

 in = messages[m_]
 loop k_ = 0 to keys.length - 1
   say 'Caesar cipher, key:' keys[k_].right(3)
   ec = caesar_encipher(in, keys[k_])
   dc = caesar_decipher(ec, keys[k_])
   say in
   say ec
   say dc
   say
   end k_
 say 'Rot-13:'
 ec = rot13(in)
 dc = rot13(ec)
 say in
 say ec
 say dc
 say
 end m_

return

method rot13(input) public static signals IllegalArgumentException

 return caesar(input, 13, isFalse)

method caesar(input = Rexx, idx = int, caps = boolean) public static signals IllegalArgumentException

 if idx < 1 | idx > 25 then signal IllegalArgumentException()
 --      12345678901234567890123456
 itab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 shift = itab.length - idx
 parse itab tl +(shift) tr
 otab = tr || tl
 if caps then input = input.upper
 cipher = input.translate(itab || itab.lower, otab || otab.lower)
 return cipher

method caesar_encipher(input = Rexx, idx = int, caps = boolean) public static signals IllegalArgumentException

 return caesar(input, idx, caps)

method caesar_decipher(input = Rexx, idx = int, caps = boolean) public static signals IllegalArgumentException

 return caesar(input, int(26) - idx, isFalse)

method caesar_encipher(input = Rexx, idx = int) public static signals IllegalArgumentException

 return caesar(input, idx, isFalse)

method caesar_decipher(input = Rexx, idx = int) public static signals IllegalArgumentException

 return caesar(input, int(26) - idx, isFalse)

method caesar_encipher(input = Rexx, idx = int, opt = Rexx) public static signals IllegalArgumentException

 return caesar(input, idx, opt)

method caesar_decipher(input = Rexx, idx = int, opt = Rexx) public static signals IllegalArgumentException

 return caesar(input, int(26) - idx, opt)

method caesar(input = Rexx, idx = int, opt = Rexx) public static signals IllegalArgumentException

 if opt.upper.abbrev('U') >= 1 then caps = isTrue
 else                               caps = isFalse
 return caesar(input, idx, caps)

method caesar(input = Rexx, idx = int) public static signals IllegalArgumentException

 return caesar(input, idx, isFalse)

method isTrue public static returns boolean

 return (1 == 1)

method isFalse public static returns boolean

 return \isTrue

</lang>

Caesar cipher, key:   1
The five boxing wizards jump quickly
Uif gjwf cpyjoh xjabset kvnq rvjdlmz
The five boxing wizards jump quickly

Caesar cipher, key:   2
The five boxing wizards jump quickly
Vjg hkxg dqzkpi ykbctfu lwor swkemna
The five boxing wizards jump quickly

Caesar cipher, key:  20
The five boxing wizards jump quickly
Nby zcpy vircha qctulxm dogj kocwefs
The five boxing wizards jump quickly

Caesar cipher, key:  25
The five boxing wizards jump quickly
Sgd ehud anwhmf vhyzqcr itlo pthbjkx
The five boxing wizards jump quickly

Caesar cipher, key:  13
The five boxing wizards jump quickly
Gur svir obkvat jvmneqf whzc dhvpxyl
The five boxing wizards jump quickly

Rot-13:
The five boxing wizards jump quickly
Gur svir obkvat jvmneqf whzc dhvpxyl
The five boxing wizards jump quickly

Caesar cipher, key:   1
Attack at dawn!
Buubdl bu ebxo!
Attack at dawn!

Caesar cipher, key:   2
Attack at dawn!
Cvvcem cv fcyp!
Attack at dawn!

Caesar cipher, key:  20
Attack at dawn!
Unnuwe un xuqh!
Attack at dawn!

Caesar cipher, key:  25
Attack at dawn!
Zsszbj zs czvm!
Attack at dawn!

Caesar cipher, key:  13
Attack at dawn!
Nggnpx ng qnja!
Attack at dawn!

Rot-13:
Attack at dawn!
Nggnpx ng qnja!
Attack at dawn!

Caesar cipher, key:   1
HI
IJ
HI

Caesar cipher, key:   2
HI
JK
HI

Caesar cipher, key:  20
HI
BC
HI

Caesar cipher, key:  25
HI
GH
HI

Caesar cipher, key:  13
HI
UV
HI

Rot-13:
HI
UV
HI

Perl

It's supposed to be a cipher, so all non-letters are dropped. <lang Perl>sub encipher {

       my ($_, $k, $decode) = @_;
       $k = 26 - $k if $decode;
       join(, map(chr(((ord(uc $_) - 65 + $k) % 26) + 65), /([a-z])/gi));

}

my $msg = 'THE FIVE BOXING WIZARDS JUMP QUICKLY'; my $enc = encipher($msg, 10); my $dec = encipher($enc, 10, 'decode');

print "msg: $msg\nenc: $enc\ndec: $dec\n";</lang>output<lang>msg: THE FIVE BOXING WIZARDS JUMP QUICKLY enc: DROPSFOLYHSXQGSJKBNCTEWZAESMUVI dec: THEFIVEBOXINGWIZARDSJUMPQUICKLY</lang>

Perl 6

<lang perl6>my @alpha = 'A' .. 'Z'; sub encrypt ( $key where 1..25, $plaintext ) {

   $plaintext.trans( @alpha Z=> @alpha.rotate($key) );

} sub decrypt ( $key where 1..25, $cyphertext ) {

   $cyphertext.trans( @alpha.rotate($key) Z=> @alpha );

}

my $original = 'THE FIVE BOXING WIZARDS JUMP QUICKLY'; my $en = encrypt( 13, $original ); my $de = decrypt( 13, $en );

.say for $original, $en, $de;

say 'OK' if $original eq all( map { .&decrypt(.&encrypt($original)) }, 1..25 );</lang>

Output:

THE FIVE BOXING WIZARDS JUMP QUICKLY
GUR SVIR OBKVAT JVMNEQF WHZC DHVPXYL
THE FIVE BOXING WIZARDS JUMP QUICKLY
OK

PicoLisp

<lang PicoLisp>(setq *Letters (apply circ (mapcar char (range 65 90))))

(de caesar (Str Key)

  (pack
     (mapcar '((C) (cadr (nth (member C *Letters) Key)))
        (chop (uppc Str)) ) ) )</lang>

Test:

: (caesar "IBM" 25)
-> "HAL"
: (caesar @ 1)
-> "IBM"

: (caesar "The quick brown fox jumped over the lazy dog's back" 7)
-> "AOLXBPJRIYVDUMVEQBTWLKVCLYAOLSHGFKVNZIHJR"
: (caesar @ (- 26 7))
-> "THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOGSBACK"

Prolog

Works with SWI-Prolog and library clpfd. <lang Prolog>:- use_module(library(clpfd)).

caesar :- L1 = "The five boxing wizards jump quickly", writef("Original : %s\n", [L1]),

% encryption of the sentence encoding(3, L1, L2) , writef("Encoding : %s\n", [L2]),

% deciphering on the encoded sentence encoding(3, L3, L2), writef("Decoding : %s\n", [L3]).

% encoding/decoding of a sentence encoding(Key, L1, L2) :- maplist(caesar_cipher(Key), L1, L2).

caesar_cipher(_, 32, 32) :- !.

caesar_cipher(Key, V1, V2) :- V #= Key + V1,

% we verify that we are in the limits of A-Z and a-z. ((V1 #=< 0'Z #/\ V #> 0'Z) #\/ (V1 #=< 0'z #/\ V #> 0'z) #\/ (V1 #< 0'A #/\ V2 #>= 0'A)#\/ (V1 #< 0'a #/\ V2 #>= 0'a)) #==> A,

% if we are not in these limits A is 1, otherwise 0. V2 #= V - A * 26,

% compute values of V1 and V2 label([A, V1, V2]).

</lang> Output :

 ?- caesar.
Original : The five boxing wizards jump quickly
Encoding : Wkh ilyh eralqj zlcdugv mxps txlfnob
Decoding : The five boxing wizards jump quickly
true .

PureBasic

The case is maintained for alphabetic characters (uppercase/lowercase input = uppercase/lowercase output) while non-alphabetic characters, if present are included and left unchanged in the result. <lang PureBasic>Procedure.s CC_encrypt(plainText.s, key, reverse = 0)

 ;if reverse <> 0 then reverse the encryption (decrypt)
 If reverse: reverse = 26: key = 26 - key: EndIf
 
 Static alphabet$ = "ABCEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 
 Protected result.s, i, length = Len(plainText), letter.s, legal
 If key < 1 Or key > 25: ProcedureReturn: EndIf  ;keep key in range
  
 For i = 1 To length
   letter = Mid(plainText, i, 1)
   legal = FindString(alphabet$, letter, 1 + reverse)
   If legal
     result + Mid(alphabet$, legal + key, 1)
   Else
     result + letter
   EndIf 
 Next 
 ProcedureReturn result

EndProcedure

Procedure.s CC_decrypt(cypherText.s, key)

 ProcedureReturn CC_encrypt(cypherText, key, 1)

EndProcedure

If OpenConsole()

 Define key, plainText.s, encryptedText.s, decryptedText.s
 
 key = Random(24) + 1 ;get a random key in the range 1 -> 25
 
 plainText = "The quick brown fox jumped over the lazy dogs.": PrintN(RSet("Plain text = ", 17) + #DQUOTE$ + plainText + #DQUOTE$)
 encryptedText = CC_encrypt(plainText, key): PrintN(RSet("Encrypted text = ", 17) + #DQUOTE$ + encryptedText + #DQUOTE$)
 decryptedText = CC_decrypt(encryptedText, key): PrintN(RSet("Decrypted text = ", 17) + #DQUOTE$ + decryptedText + #DQUOTE$)
 
 Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
 CloseConsole()

EndIf</lang> Sample output:

    Plain text = "The quick brown fox jumped over the lazy dogs."
Encrypted text = "Znk waoiq hxuct lud pasvkj ubkx znk rgfe jumy."
Decrypted text = "the quick brown fox jumped over the lazy dogs."

Alternate solution

Here is an alternate and more advanced form of the encrypt procedure. It improves on the simple version in terms of speed, in case Caesar is using the cipher on some very long documents. It is meant to replace the encrypt procedure in the previous code and produces identical results. <lang PureBasic>Procedure.s CC_encrypt(text.s, key, reverse = 0)

 ;if reverse <> 0 then reverse the encryption (decrypt)
 Protected i, *letter.Character, *resultLetter.Character, result.s = Space(Len(text))
 
 If reverse: key = 26 - key: EndIf
 If key < 1 Or key > 25: ProcedureReturn: EndIf  ;exit if key out of range
  
 *letter = @text: *resultLetter = @result
 While *letter\c
   Select *letter\c
     Case 'A' To 'Z'
       *resultLetter\c = ((*letter\c - 65 + key) % 26) + 65
     Case 'a' To 'z'
       *resultLetter\c = ((*letter\c - 97 + key) % 26) + 97
     Default
       *resultLetter\c = *letter\c
   EndSelect
   *letter + SizeOf(Character): *resultLetter + SizeOf(Character)
 Wend
 ProcedureReturn result

EndProcedure</lang>

Python

<lang Python>def caesar(s, k, decode = False): if decode: k = 26 - k return "".join([chr((ord(i) - 65 + k) % 26 + 65) for i in s.upper() if ord(i) >= 65 and ord(i) <= 90 ])

msg = "The quick brown fox jumped over the lazy dogs" print msg enc = caesar(msg, 11) print enc print caesar(enc, 11, decode = True)</lang>Output:<lang>The quick brown fox jumped over the lazy dogs ESPBFTNVMCZHYQZIUFXAPOZGPCESPWLKJOZRD THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOGS</lang>

Racket

<lang scheme>#lang racket

(define A (char->integer #\A)) (define Z (char->integer #\Z)) (define a (char->integer #\a)) (define z (char->integer #\z))

(define (rotate c n)

 (define cnum (char->integer c))
 (define (shift base) (integer->char (+ base (modulo (+ n (- cnum base)) 26))))
 (cond [(<= A cnum Z) (shift A)]
       [(<= a cnum z) (shift a)]
       [else c]))

(define (caesar s n)

 (list->string (for/list ([c (in-string s)]) (rotate c n))))

(define (encrypt s) (caesar s 1)) (define (decrypt s) (caesar s -1))</lang> Example: <lang scheme>> (define s (encrypt "The five boxing wizards jump quickly.")) > s "Uif gjwf cpyjoh xjabset kvnq rvjdlmz." > (decrypt s) "The five boxing wizards jump quickly."</lang>

Ruby

Translation of: Perl 6

<lang ruby>@atoz = Hash.new do |hash, key|

 str = ('A'..'Z').to_a.rotate(key).join("")
 hash[key] = (str << str.downcase)

end

def encrypt(key, plaintext)

 (1..25) === key or raise ArgumentError, "key not in 1..25"
 plaintext.tr(@atoz[0], @atoz[key])

end

def decrypt(key, ciphertext)

 (1..25) === key or raise ArgumentError, "key not in 1..25"
 ciphertext.tr(@atoz[key], @atoz[0])

end

original = "THEYBROKEOURCIPHEREVERYONECANREADTHIS" en = encrypt(3, original) de = decrypt(3, en)

[original, en, de].each {|e| puts e}

puts 'OK' if

 (1..25).all? {|k| original == decrypt(k, encrypt(k, original))}</lang>

The Ruby translation saves the rotations in an @atoz hash. (The Perl 6 code called rotate() during each encrypt or decrypt.) The code block on Hash.new makes the rotation and puts it in the hash.

  • @atoz[0] becomes "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
  • @atoz[3] becomes "DEFGHIJKLMNOPQRSTUVWXYZABCdefghijklmnopqrstuvwxyzabc",
  • and so on.

When the key is 3, encryption uses String#tr(@atoz[0], @atoz[3]) to substitute characters. Decryption uses String#tr(@atoz[3], @atoz[0]).

To make a rotation, Ruby is worse than Perl 6. Ruby needs two extra conversions: the code ('A'..'Z').to_a.rotate(key).join("") uses to_a to convert a Range to an Array, to access the Array#rotate method. Then join("") converts the rotated Array to a String, because String#tr needs a String, not an Array.

Scala

<lang scala>object Caesar {

 private val alphaU='A' to 'Z'
 private val alphaL='a' to 'z'
 def encode(text:String, key:Int)=text.map{
   case c if alphaU.contains(c) => rot(alphaU, c, key)
   case c if alphaL.contains(c) => rot(alphaL, c, key)
   case c => c
 }
 def decode(text:String, key:Int)=encode(text,-key)
 private def rot(a:IndexedSeq[Char], c:Char, key:Int)=a((c-a.head+key+a.size)%a.size)

}</lang> <lang scala>val text="The five boxing wizards jump quickly" println("Plaintext => " + text) val encoded=Caesar.encode(text, 3) println("Ciphertext => " + encoded) println("Decrypted => " + Caesar.decode(encoded, 3))</lang> Output:

Plaintext  => The five boxing wizards jump quickly
Ciphertext => Wkh ilyh eralqj zlcdugv mxps txlfnob
Decrypted  => The five boxing wizards jump quickly

Seed7

<lang seed7>$ include "seed7_05.s7i";

const func string: rot (in string: stri, in integer: encodingKey) is func

 result
   var string: encodedStri is "";
 local
   var char: ch is ' ';
   var integer: index is 0;
 begin
   encodedStri := stri;
   for ch key index range stri do
     if ch >= 'a' and ch <= 'z' then
       ch := chr((ord(ch) - ord('a') + encodingKey) rem 26 + ord('a'));
     elsif ch >= 'A' and ch <= 'Z' then
       ch := chr((ord(ch) - ord('A') + encodingKey) rem 26 + ord('A'));
     end if;
     encodedStri @:= [index] ch;
   end for;
 end func;

const proc: main is func

 local
   const integer: exampleKey is 3;
   const string: testText is "The five boxing wizards jump quickly";
 begin
   writeln("Original:  " <& testText);
   writeln("Encrypted: " <& rot(testText, exampleKey));
   writeln("Decrypted: " <& rot(rot(testText, exampleKey), 26 - exampleKey));
 end func;</lang>

Output:

Original:  The five boxing wizards jump quickly
Encrypted: Wkh ilyh eralqj zlcdugv mxps txlfnob
Decrypted: The five boxing wizards jump quickly

Tcl

<lang tcl>package require Tcl 8.6; # Or TclOO package for 8.5

oo::class create Caesar {

   variable encryptMap decryptMap
   constructor shift {

for {set i 0} {$i < 26} {incr i} { # Play fast and loose with string/list duality for shorter code append encryptMap [format "%c %c %c %c " \ [expr {$i+65}] [expr {($i+$shift)%26+65}] \ [expr {$i+97}] [expr {($i+$shift)%26+97}]] append decryptMap [format "%c %c %c %c " \ [expr {$i+65}] [expr {($i-$shift)%26+65}] \ [expr {$i+97}] [expr {($i-$shift)%26+97}]] }

   }
   method encrypt text {

string map $encryptMap $text

   }
   method decrypt text {

string map $decryptMap $text

   }

}</lang> Demonstrating: <lang tcl>set caesar [Caesar new 3] set txt "The five boxing wizards jump quickly." set enc [$caesar encrypt $txt] set dec [$caesar decrypt $enc] puts "Original message = $txt" puts "Encrypted message = $enc" puts "Decrypted message = $dec"</lang> Output:

Original message  = The five boxing wizards jump quickly.
Encrypted message = Wkh ilyh eralqj zlcdugv mxps txlfnob.
Decrypted message = The five boxing wizards jump quickly.

TUSCRIPT

<lang tuscript> $$ MODE TUSCRIPT text="THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG" PRINT "text orginal ",text

abc="ABCDEFGHIJKLMNOPQRSTUVWXYZ",key=3,caesarskey=key+1 secretbeg=EXTRACT (abc,#caesarskey,0) secretend=EXTRACT (abc,0,#caesarskey) secretabc=CONCAT (secretbeg,secretend)

abc=STRINGS (abc,":</:"),secretabc=STRINGS (secretabc,":</:") abc=SPLIT (abc), secretabc=SPLIT (secretabc) abc2secret=JOIN(abc," ",secretabc),secret2abc=JOIN(secretabc," ",abc)

BUILD X_TABLE abc2secret=* DATA {abc2secret}

BUILD X_TABLE secret2abc=* DATA {secret2abc}

ENCODED = EXCHANGE (text,abc2secret) PRINT "text encoded ",encoded

DECODED = EXCHANGE (encoded,secret2abc) PRINT "encoded decoded ",decoded </lang> Output:

text orginal    THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
text encoded    WKH TXLFN EURZQ IRA MXPSV RYHU WKH ODCB GRJ
encoded decoded THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 

Ursala

The reification operator (-:) generates efficient code for applications like this given a table of inputs and outputs, which is obtained in this case by zipping the alphabet with itself rolled the right number of times, done separately for the upper and lower case letters and then combined. <lang Ursala>#import std

  1. import nat

enc "n" = * -:~&@T ^p(rep"n" ~&zyC,~&)~~K30K31X letters # encryption function dec "n" = * -:~&@T ^p(~&,rep"n" ~&zyC)~~K30K31X letters # decryption function

plaintext = 'the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY'

  1. show+ # exhaustive test

test = ("n". <.enc"n",dec"n"+ enc"n"> plaintext)*= nrange/1 25</lang> output:

uif gjwf cpyjoh xjabset kvnq rvjdlmz UIF GJWF CPYJOH XJABSET KVNQ RVJDLMZ
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
vjg hkxg dqzkpi ykbctfu lwor swkemna VJG HKXG DQZKPI YKBCTFU LWOR SWKEMNA
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
wkh ilyh eralqj zlcdugv mxps txlfnob WKH ILYH ERALQJ ZLCDUGV MXPS TXLFNOB
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
xli jmzi fsbmrk amdevhw nyqt uymgopc XLI JMZI FSBMRK AMDEVHW NYQT UYMGOPC
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
ymj knaj gtcnsl bnefwix ozru vznhpqd YMJ KNAJ GTCNSL BNEFWIX OZRU VZNHPQD
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
znk lobk hudotm cofgxjy pasv waoiqre ZNK LOBK HUDOTM COFGXJY PASV WAOIQRE
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
aol mpcl ivepun dpghykz qbtw xbpjrsf AOL MPCL IVEPUN DPGHYKZ QBTW XBPJRSF
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
bpm nqdm jwfqvo eqhizla rcux ycqkstg BPM NQDM JWFQVO EQHIZLA RCUX YCQKSTG
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
cqn oren kxgrwp frijamb sdvy zdrltuh CQN OREN KXGRWP FRIJAMB SDVY ZDRLTUH
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
dro psfo lyhsxq gsjkbnc tewz aesmuvi DRO PSFO LYHSXQ GSJKBNC TEWZ AESMUVI
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
esp qtgp mzityr htklcod ufxa bftnvwj ESP QTGP MZITYR HTKLCOD UFXA BFTNVWJ
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
ftq ruhq najuzs iulmdpe vgyb cguowxk FTQ RUHQ NAJUZS IULMDPE VGYB CGUOWXK
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
gur svir obkvat jvmneqf whzc dhvpxyl GUR SVIR OBKVAT JVMNEQF WHZC DHVPXYL
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
hvs twjs pclwbu kwnofrg xiad eiwqyzm HVS TWJS PCLWBU KWNOFRG XIAD EIWQYZM
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
iwt uxkt qdmxcv lxopgsh yjbe fjxrzan IWT UXKT QDMXCV LXOPGSH YJBE FJXRZAN
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
jxu vylu renydw mypqhti zkcf gkysabo JXU VYLU RENYDW MYPQHTI ZKCF GKYSABO
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
kyv wzmv sfozex nzqriuj aldg hlztbcp KYV WZMV SFOZEX NZQRIUJ ALDG HLZTBCP
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
lzw xanw tgpafy oarsjvk bmeh imaucdq LZW XANW TGPAFY OARSJVK BMEH IMAUCDQ
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
max ybox uhqbgz pbstkwl cnfi jnbvder MAX YBOX UHQBGZ PBSTKWL CNFI JNBVDER
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
nby zcpy vircha qctulxm dogj kocwefs NBY ZCPY VIRCHA QCTULXM DOGJ KOCWEFS
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
ocz adqz wjsdib rduvmyn ephk lpdxfgt OCZ ADQZ WJSDIB RDUVMYN EPHK LPDXFGT
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
pda bera xktejc sevwnzo fqil mqeyghu PDA BERA XKTEJC SEVWNZO FQIL MQEYGHU
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
qeb cfsb ylufkd tfwxoap grjm nrfzhiv QEB CFSB YLUFKD TFWXOAP GRJM NRFZHIV
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
rfc dgtc zmvgle ugxypbq hskn osgaijw RFC DGTC ZMVGLE UGXYPBQ HSKN OSGAIJW
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY
sgd ehud anwhmf vhyzqcr itlo pthbjkx SGD EHUD ANWHMF VHYZQCR ITLO PTHBJKX
the five boxing wizards jump quickly THE FIVE BOXING WIZARDS JUMP QUICKLY