Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotating letters in a string so that each letter is shifted to another letter by n places

Tags:

ruby

I have been tasked with coming up with a way of encoding a string. Among other things, I need to shift each letter by a given number but the transformed letter must be a letter (circular shift).

I have got the following code so far:

def play_pass(str, n)
  letters = ('a'..'z').to_a
  str.chars.map {|x| letters.include?(x.downcase) ? (x.ord + n).chr : x}.join
end

This works for most letters

My problem is that if I am trying to shift y by 2 places, I should get a but instead I get the character [

Where am I going wrong?

like image 855
KVyas Avatar asked Jul 18 '15 09:07

KVyas


1 Answers

Try this:

def play_pass(str, n)
  letters = ('a'..'z').to_a
  str.chars.map {|x| letters.include?(x.downcase) ? 
     letters[letters.find_index(x.down_case) + n - letters.size] : x}.join
end

p play_pass("abcdefghijklmnopqrstuvwxyz", 2)

Output

"cdefghijklmnopqrstuvwxyzab"
[Finished in 0.3s]

How it works

letters is an array of chars a to z just the way OP has in his code. We iterate over all chars in str, and find its index in letters array. Then we add n to that index to get the shifted character. To avoid falling off the array, we subtract letters.size (in this case 26), so that the our lookup into letters is done using value between 0 and 25.

For example: In the scenario that OP pointed out, if the character to be shifted was y, then, adding 2 to its index in letters will give us shifted index 26 (24 is index of y in letters array, 2 is number characters we are shifting in the test case) - To make letters behave like circular array, and not encounter index out of bound type of exception, we subtract letters.size from 26 shifted index. Thus, we get index 0, which represents char a which is what we are interested in.

Another example is case of a - Here the shifted index will be 0 + 2 = 2. When we subtract letters.size from it, we get -24. Ruby allows negative indexes wherein lookup of array element is done from reverse, and it will resolve to correct element. Index -1 is same as Index (size-1), similarly, index value of -size is equal to index 0.

like image 189
Wand Maker Avatar answered Nov 15 '22 03:11

Wand Maker