Caesar cipher: Difference between revisions
m (→{{header|J}}) |
(→{{header|AutoHotkey}}: noted Unicode dependency for golfed solution) |
||
Line 113: | Line 113: | ||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
This ungodly solution is an attempt at code-golf. It requires input to be all-caps alphabetic |
This ungodly solution is an attempt at code-golf. It requires input to be all-caps alphabetic, only works on AutoHotkey_L Unicode, and might not run on x64 |
||
<lang AutoHotkey>n=2 |
<lang AutoHotkey>n=2 |
||
s=HI |
s=HI |
Revision as of 21:58, 19 September 2011
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
Note: This specimen retains the original Ada coding style.
<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#;
- 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, only works on AutoHotkey_L Unicode, 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>
- include <stdlib.h>
- include <string.h>
- define caesar(x) rot(13, x)
- define decaesar(x) rot(13, x)
- 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);
- "HAL"
CaesarCipher("Vgg cphvi wzdibn vmz wjmi amzz viy zlpvg di ydbidot viy mdbcon.", 5);
- "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>
If we instead assume the task only requires we treat upper case characters:
<lang j>CAESAR=:1 :'(26|m&+)&.((26{.64}.a.)&i.)'</lang>
Example use:<lang j> 20 CAESAR 'HI' BC</lang>
Java
<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
<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
- 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'
- 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