in Vigenere Cipher :: A long time Delphi developer, Alan Lloyd had a few comments on the recently published Vigenere Cipher - Delphi Implementation - Fancy Delphi Application Contest Entry #49.
Alan suggests:
While we have loads of computation power & memory available today, I think as a professional it is better to code quicker than slower, unless it makes code unclear.
In the posted Vigenere code . . .
- String memory allocation/re-allocation is slow so avoid ConCat(), String + String (even though its quicker than ConCat), and Delete(). Better to SetLength for strings and use index accessing for characters.
- Use 'for' loops rather than 'while' loops.
- Reduce the code for every character. Check for bEncrypt before entering repeated similar code in a 'for' loop for each character action.
- IMO sTable should be initialised before use by := '' or SetLength(). AIUI variables in functions are not zeroed, and you might be using garbage.
- Crypt by re-referencing the key as given rather that using multiple keys up to the source length.
function Vigenere(Src, Key : string; Encrypt : boolean) : string;
const
OrdMinChar : integer = Ord('A');
OrdMaxChar : integer = Ord('Z');
IncludeChars : set of char = ['A'..'Z'];
var
CharRangeCount, i, j, KeyLen, KeyInc, SrcOrd, CryptOrd : integer;
SrcA : string;
begin
CharRangeCount := OrdMaxChar - OrdMinChar + 1;
KeyLen := Length(Key);
SetLength(SrcA, Length(Src));
If Encrypt then
begin
// transfer only included characters to SrcA for encryption
j := 1;
for i := 1 to Length(Src) do
begin
if (Src[i] in IncludeChars) then
begin
SrcA[j] := Src[i];
inc(j);
end;
end;
SetLength(SrcA, j - 1);
end;
SetLength(Result, Length(SrcA));
if Encrypt then
begin
// Encrypt to Result
for i := 1 to Length(SrcA) do
begin
SrcOrd := Ord(Src[i]) - OrdMinChar;
KeyInc := Ord(Key[((i - 1 ) mod KeyLen)+ 1]) - OrdMinChar;
CryptOrd := ((SrcOrd + KeyInc) mod CharRangeCount) + OrdMinChar;
Result[i] := Char(CryptOrd);
end;
end;
else
begin
// Decrypt to Result
for i := 1 to Length(SrcA) do
begin
SrcOrd := Ord(Src[i]) - OrdMinChar;
KeyInc := Ord(Key[((i - 1 ) mod KeyLen)+ 1]) - OrdMinChar;
CryptOrd := ((SrcOrd - KeyInc + CharRangeCount) mod CharRangeCount) + OrdMinChar;
// KeyInc may be larger than SrcOrd
Result[i] := Char(CryptOrd);
end;
end;
end;


Thanks for the tips, I must have been mistaken with “While” loop as I have always thought this to be faster than a “for” loop as suggested by many web site. I do normally use string + string to concatenate my string but due to submitting this code I thought it would be best to make it readable and use proper delphi functions. Im going to do a speed test just out of interested. Once again I really appreciate your comments and tips, Im a self taught programmer and like to receive suggestions and ideas to improve my programming skills.
After some speed tests I came to the conclusion that the spped diffrents is 0.4 ms which is not bad considering thats less than half a milli second. This result is when I Change my table size to the same as yours 26 char’s Uppercase.
Your Function: 4.4ms (average over 10 calls to the function)
My Function: 4.2ms (average over 10 calls to function)
The surprising part of this test is when using ALL 94 readable chars in my function the first call was done in 1ms but then calling the function again grew to 9ms. Strange…
Anyway it does clear a couple of small things up
1. ConCat is NOT slower than using “+” (got same results using both)
2. using for loop over while has no difference (Otherwise the difference would have been alot larger than 0.4ms)
Some other test that might yield different results would to use a “Repeat” “untill” loop which i am guessing would speed things up.
Conclusion:
Your routine is faster, but by such a small amount Im not even sure its worth talking about(0.4ms)
Thanks again for taking the time to pass some comments and share your excellent work.
Anyone want to take a crack at it? It may or may not pertain to something in Hawaii…thanks!
Riches wait upon this path
Seek and find acclaim
Your wits must be the sharper
If you wish to beat this game.
Within a code that Bacon knew
Hidden here upon these lines
Those who unlock its secret
Are rewarded first in time.
The key is for the Vigenere,
A cipher hard as steel
For there within its mighty lines
More treasures are revealed.
Code:
smlrgtbkegzrskwysxdcneilokltgpmdvxehvkbq