Next: Improved Caesar-like ciphers Up: fsqFsHn sGGousG Previous: Defining functions with proc;

# Caesar cipher redux

Now that we know about proc, let's implement the Caesar cipher again, this time with an alphabet of our choosing.

First, we define a global variable Alphabet that lists all the characters we intend to encode. We would like to be able to distinguish all characters which print out, as well as blanks (that is, those which you have keys for on your keyboard). To avoid typing in the full list of characters we want4.13, we generate a list of all the integers less than 256 and convert it to a character string with convert(,bytes). Then we use Select and IsPrintable to pick out the usual printable characters. Finally, since we would like to have a space and a newline as characters in our alphabet, we add them to the resulting string with cat.

>
Alphabet := cat("", Select(IsPrintable,convert([seq(i,i=1..255)],bytes)));


We will use this particular alphabet regularly in the next few sections.

Next, we define two functions which perform the analogue of convert(,bytes), but with our special alphabet. ListToString will take a list of integers and replace it with the character from that position in Alphabet, and StringToList does the reverse process. For each character in the input string, StringToList uses SearchText to find its position in Alphabet. We need to subtract one from this position because we would like our characters to be numbered from 0 rather than 1. Thus, in the Alphabet above, \t is character 0, and the numeric code for is 96. Alphabet is declared as a global variable.

>
StringToList := proc(text::string)
local i;
global Alphabet;
[seq(SearchText(text[i],Alphabet)-1, i=1..length(text))];
end:


>
ListToString := proc(numlist::list(nonnegint))
local i;
global Alphabet;
cat(seq(Alphabet[numlist[i]+1], i=1..nops(numlist)));
end:


Now the Caesar cipher is written in terms of these functions. Note that since 0 corresponds to a printable character, we don't have to add and subtract 1 as before.

>
Caesar2:= proc(plaintext::string, shift::integer)
local textnum,codenum,i,p;
global Alphabet;

p       := length(Alphabet);
textnum := StringToList(plaintext);
codenum := [seq( modp(textnum[i]+shift, p), i=1..length(plaintext)) ];
ListToString(codenum);
end:


It works as follows.

• We are given a plaintext message, and a shift amount. The temporary variables that we will use during the conversion process are declared as local, and the Alphabet is declared as global.
• The number of characters in the alphabet is saved as p.
• The plaintext is converted to a list of numbers called textnum.
• Each number in textnum is shifted, and the result is taken mod p. Note that since StringToList yields result in {0, 1,..., p - 1}, we don't have to monkey around to get the result into the proper range like we did in the first Caesar (§2.2, p. ). Also note that we use modp(a,p) to compute a mod p, instead of writing a mod p as before. Either way works fine.
• Finally, the result is converted back to characters with ListToString.

Let's try it out.

>
Caesar2("Veni, Vidi, Vici",3);


To decode, we can just use the negative of the shift amount.

>
Caesar2(

>
text:="I have heard the mermaids singing, each to each.
I do not think that they will sing to me.";


In this sample, we have used a text which contains a newline character. Maple represents this as \n inside a text string. Since we will treat the newline as a regular character, it too will encode to something. If you look carefully at the output below, you can probably pick it out.

>
Caesar2(text,64);


>
Caesar2(

If we would like to see the decrypted text with the newlines expanded, we need to use printf.

>
printf(

One thing that we should check is what happens if our message should contain a character that is not in our alphabet. Rather than changing our text, we'll dramatically shorten the alphabet.

>
Alphabet:="abcdefghijklmnop_";


Now let us go then, you and I, and re-encode the test message using the new alphabet, but with a shift of zero. Ordinarily, a shift by 0 would not change the text at all. But with the shortened alphabet, something happens to the characters that aren't mentioned.

>
Caesar2(text,0);


Can you explain why this happens?

#### Footnotes

... want4.13
For versions prior to Maple 7, just type in the desired alphabet directly

Next: Improved Caesar-like ciphers Up: fsqFsHn sGGousG Previous: Defining functions with proc;

Translated from LaTeX by Scott Sutherland
2002-08-29