Title: ROT47 a simple Substitution cipher function V2
Question: How to implement the Rot47 (rotate by 47 places) the simple substitution cipher function (Rot5, Rot13 and Rot18 too) ?
Answer:
ROT47 is a derivative of ROT13 which, in addition to scrambling the basic letters, also treats numbers and common symbols. Instead of using the sequence AZ as the alphabet, ROT47 uses a larger set of characters from the common character encoding known as ASCII. Specifically, all 7-bit printable characters, excluding space, from decimal 33 '!' through 126 '~' are rotated by 47 positions, without special preserving of case.
Here is the function
--------------------
function Rot47(AStr: String): String;
function Rot47Char(AChr: Char): Char;
var
iAsc: Integer;
begin
Result := ' ';
if (AChr = ' ') then
Exit;
iAsc := Ord(AChr) + 47;
if (iAsc 126) then
iAsc := iAsc - 94;
if (iAsc then
iAsc := iAsc + 94;
Result := Chr(iAsc);
end;
var
I: Integer;
begin
Result := '';
for I := 1 to Length(AStr) do
Result := Result + Rot47Char(Astr[I]);
end;
The usage is :
--------------
ShowMessage(Rot47('Laurent')); // -- display '{2FC6?E'
And
ShowMessage(Rot47('{2FC6?E')); // -- display 'Laurent'
-----------------------------------------------------------------------------------
New version (V2) that integrates all variation of Rotate by Rot5, Rot13, Rot18 and Rot47 :
The four ROT algorithms ROT5, ROT13, ROT18 and ROT47 vary in the characters that can be encoded/decoded:
* ROT5 covers the numbers 0-9.
* ROT13 covers the 26 upper and lower case letters of the Latin alphabet (A-Z, a-z).
* ROT18 is a combination of ROT5 and ROT13.
* ROT47 covers all printable ASCII characters, except empty spaces. Besides numbers and the letters of the Latin alphabet, the following characters are included: !"#$%&'()*+,-./:;?[\]^_`{|}~
-----------------------------------------------------------------------------------
function RotateBy(AStr: String; const ARotate: Integer = 47): String;
function RotateChar(AChr: Char; ARotate: Integer): Char;
var
iStart, iRotate: Integer;
begin
iStart := 0;
case ARotate of
5: if AChr in ['0'..'9'] then
begin
iStart := 48; // '0'
iRotate := 5;
end;
13: if AChr in ['A'..'Z'] then
begin
iStart := 65; // 'A'
iRotate := 13;
end
else if Achr in ['a'..'z'] then
begin
iStart := 97; // 'a'
iRotate := 13;
end;
18: if AChr in ['0'..'9'] then
begin
iStart := 48; // '0'
iRotate := 5;
end
else if AChr in ['A'..'Z'] then
begin
iStart := 65; // 'A'
iRotate := 13;
end
else if AChr in ['a'..'z'] then
begin
iStart := 97; // 'a'
iRotate := 13;
end;
47: if AChr in ['!'..'~'] then
begin
iStart := 33; // '!'
iRotate := 47;
end
end;
if iStart 0 then
Result := Chr(iStart + ((Ord(AChr) - iStart + iRotate) mod (iRotate * 2)))
else
Result := AChr;
end;
var
I: Integer;
begin
Result := '';
for I := 1 to Length(AStr) do
Result := Result + RotateChar(AStr[I], ARotate);
end;
The usage of this function is :
-------------------------------
ShowMessage(RotateBy('Laurent 2007', 5)); // Display 'Laurent 7552'
ShowMessage(RotateBy('Laurent 2007', 13)); // Display 'Ynherag 2007'
ShowMessage(RotateBy('Laurent 2007', 18)); // Display 'Ynherag 7552'
ShowMessage(RotateBy('Laurent 2007')); // Display '{2FC6?E a__f'