Caesar Cipher in Ruby

I haven't implemented a Caesar Cipher since way back when I started learning C. I remember vividly the excitement of the problem, it was complex enough that it felt daunting but simple enough that I felt like I could tackle it.

"What is a Caesar Cipher?", I hear none of you ask. Well if you are one of the rare few that are interested in code and still don't know, read this

Since I'm now a professional ruby developer I thought I'd give it another go. It's a lot simpler than I remember it!

Here goes

class CaesarCipher

  ALLOWED_CHARACTERS = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
    'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
    'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', '0', '!', '@', ',', '.', '?', '\'', '"', ' '
  ]

  attr_accessor :offset

  def initialize(offset)
    @offset = offset
  end

  def encrypt(plain_text)
    encrypted_chars = plain_text.each_char.map do |char|
      corresponding_character(char, :+)
    end
    return encrypted_chars.join
  end

  def decrypt(encrypted_text)
    plain_chars = encrypted_text.each_char.map do |char|
      corresponding_character(char, :-)
    end
    return plain_chars.join
  end

  private

  def corresponding_character(char, operator)
    char_index = ALLOWED_CHARACTERS.index(char)
    offset_index = char_index.public_send(operator, offset)
    corrected_index = offset_index % ALLOWED_CHARACTERS.length
    return ALLOWED_CHARACTERS[corrected_index]
  end
end  

Try it out, let me know if you find any bugs or have any improvements/questions etc.

Joe Woodward

Read more posts by this author.