Search code examples
rubycaesar-cipher

Caesar's cipher in Ruby


I'm working on a Caesar's cipher problem with a left shift of 1 but having a difficulty getting started. The prompt asks me to look at the String method #ord and the Integer method #chr in the Ruby Documentation. And letter 'a' has to be shifted to 'z'...

Below is my work..

def solve_cipher(string, n)
letters = ['a'..'z']
string.map {|x| letters.include?(x.ord + n).chr : x}.join

Thanks for any advice...!


Solution

  • You need to split your word into the individual characters. Then you need to convert the characters to ints with ord so you can do arithmetic. The arithmetic operation is to add an offset relative to 'a', modulo 26, so that the result maps to a different offset from 'a' which will result in a new character. Change the result back to character with chr, and join the characters back together to form a string.

    Here's one possible implementation which accommodates both upper and lower case letters:

    def shift_char(c, base, offset)
      (((c.ord - base) + offset) % 26 + base).chr
    end
    
    def cipher(s, offset)
      s.chars.map do |c|
        case c
        when 'a'..'z'
          shift_char(c, 'a'.ord, offset)
        when 'A'..'Z'
          shift_char(c, 'A'.ord, offset)
        else
          c
        end
      end.join
    end
    
    cipher_text = cipher('Now is the time for all good men...', 13)
    p cipher_text       # "Abj vf gur gvzr sbe nyy tbbq zra..."
    original_text = cipher(cipher_text, 13)
    p original_text     # "Now is the time for all good men..."