Robert Eisele
Engineer, Systems Architect and DBA

Codefights: caesarian

Original problem

Caesarian shift (Caesar cipher) is a method used in cryptography where a string message is encrypted by shifting the letters n times.

You are given an integer n, which can be positive, negative or zero. Positive values indicate right shifts, and negative values indicate left shifts.

Given a message and n, return message encrypted by the shift n.

Example

  • For message = "abc" and n = 3, the output should be

    caesarian(message, n) = "def".

    "a", shifted to the right 3 times, becomes "d", "b" becomes "e"and "c" becomes "f".

  • For message = "egg" and n = -1, the output should be

    caesarian(message, n) = "dff".

Input/Output

  • [time limit] 4000ms (js)
  • [input] string message

    The message to be encrypted.

    Constraints:

    0 ≤ message.length ≤ 500.

  • [input] integer n

    The shift value.

    Constraints:

    -2 · 109 ≤ n ≤ 2 · 109.

  • [output] string

    Encrypted message.

Solution

I worked on a Caesar Chiffre Decoder, which probabilistically guesses the right key. For this problem, we get the key and simply have to encode a given message. So the hard part is again, how can we find a minimalistic solution. I tried different things, but I'll explain only my final submission here. In order to loop over the ASCII values of a string in JavaScript, it's a fuss of function calls like String.fromCharCode(), charCodeAt() and so on. A nice alternative is using the Buffer object, which has a copy constructor for strings and can be casted to Uint8Array like this:

new Uint8Array(new Buffer("hello"))

Buffer doesn't require the new-keyword and also the explicit call to Uint8Array is not needed, since there is the spread-syntax in ES6, which minimizes the code to:

[...Buffer("hello")]

Now that we have an array of the ASCII values of the string, we can map the values in order to shift them accoring to the given offset:

[...Buffer("hello")].map(x => f(x))

We now need to map the old ASCII-values to the new shifted values. In a perfectly aligned world, we would simply subtract 97 from the value in order to make 'a' zero, add the required shift and re-add the subtracted 97 after taking the modulo for the given congruence relation.

\[f(x) = (x - 97 + n) \bmod 26 + 97 \]

As the shift parameter \(n\) can become quite small, we need to shrink it as the JavaScript modulo operator is not the same as the mathematical modulo. We can move in the modulo relaton, which eliminates the -97, which becomes +7 and n % 26 gives us the interval \([-25, 25]\), which is okay because we add it to lowercase letters afterwards - which are always \(\geq 97\):

\[f(x) = (x + 7 + n\bmod 26) \bmod 26 + 97 \]

Bringing together these two pieces leads to the following solution:

b=Buffer
caesarian = (m, n) =>
   ""+b([...b(m)].map(x => (n % 26 + x + 7) % 26 + 97))

Go to overview