1
$\begingroup$

This is my first non-trivial Mathematica notebook, which I wrote for a cryptology homework. It encrypts/decrypts strings using an affine cipher. Is the code readable/idiomatic? How could it be improved? (I'm using version 10, so I don't have the ModularInverse function).

toNum[c_] := LetterNumber[c] - 1

toChar[n_] := Alphabet[][[n + 1]]

encryptAffine[m_, b_] := StringJoin[
   toChar[
      Mod[m toNum[#] + b, 26] 
      ] & /@ Characters[#]
   ] &

decryptAffine[m_, b_] := StringJoin[
   toChar[
      Mod[
       PowerMod[m, -1, 26]*(toNum[#] - b),
       26
       ]
      ] & /@ Characters[#]
   ] &

decryptAffine[3, 7][encryptAffine[3, 7]["helloworld"]]


(* "helloworld" *)
$\endgroup$

1 Answer 1

4
$\begingroup$

Expressive enough for my taste. But a bit shorter and much faster (by 3 orders of magnitude) would be to use ToCharacterCode and FromCharacterCode as follows:

decryptAffine2[m_, b_] := FromCharacterCode[
    Mod[PowerMod[m, -1, 26] (ToCharacterCode[#] - (97 + b)), 26] + 97
    ] &;

f = decryptAffine[3, 7];
g = decryptAffine2[3, 7];
s = StringJoin[RandomChoice[Alphabet[], 10000]];
r1 = f[s]; // AbsoluteTiming // First
r2 = g[s]; // AbsoluteTiming // First
r1 == r2

1.28523

0.000329

True

ToCharacterCode has the advantage that it transforms a string into a packed array. Moreover the arithmetic operations are vectorized so that they can applied componentwise to arrays. This often provides enormous speedup compared to using Map.

$\endgroup$
1
  • $\begingroup$ Thanks for the tip, hadn't heard of that function! $\endgroup$ Aug 19, 2018 at 22:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.