Menu-based Caesar Cipher with encryption and decryption I am about to start a very large project in Ruby. To get myself in the Ruby mindset I have been doing all of my homework and other side work in Ruby. I am hoping that some of you who know Ruby very well can look at this small program I have written and point out areas that aren't written in a Ruby-like fashion. Any and all tips and criticisms would be appreciated.

This program is a menu-based Caesar Cipher with encryption and decryption.

KEY = 3 
$caesar_map = {}

#initializes the caesar_map and reads input from the user
#starting point of the program
def init()
  #create empty hashes
  plain_alphabet  = {}
  cipher_alphabet = {}

  #fill in the alphabet hashes with the letter and its position
  #in the english alphabet
  "a".upto("z") {|x| plain_alphabet[x]  = ((x[0] - "a"[0]) % 26) }
  "A".upto("Z") {|x| cipher_alphabet[x] = ((x[0] - "A"[0]) % 26) }

  #fill in the caesar_map, maps every letter KEY positions
  #to the right in the alphabet
  plain_alphabet.each do |k,v|
    $caesar_map[k] = cipher_alphabet.index((v+KEY) % 26)
    #puts "key: #{k} mapped value: #{cipher_alphabet.index((v+3) % 26)}"
  end
  #special case, I want spaces to be maintained in the messages
  $caesar_map[" "] = " "

  #print menu
  choice = -1
  while(choice != 3)
    puts "What would you like to do?"
    puts "\n1. Encrypt a message"
    puts "\n2. Decrypt a message"
    puts "\n3. Exit\n"

    choice = Integer(gets.chomp)

    if(choice == 1)
      puts "Please enter a message you would like to Encrypt\n"
      message = gets.chomp
      encrypt(message)
    elsif(choice == 2)
      puts "Please enter a message you would like to Decrypt\n"
      message = gets.chomp
      decrypt(message)
    elsif(choice == 3)
      abort("Exiting...")
    else
      puts "You didn't enter a valid choice. Enter a number between 1..3\n"
    end
  end
end

#encrypts a plaintext message using the caesar cipher
def encrypt(plaintext)
  #make sure the message is in lowercase
  plaintext.downcase!
  ciphertext = ""

  #fill in the ciphertext with mapping information in the caesar_map
  plaintext.split("").each do |c|
    ciphertext += $caesar_map[c]
  end

  #print the encrypted ciphertext
    puts "\n plaintext: #{plaintext}\nciphertext: #{ciphertext}\n\n"
end

#decrypts a ciphertext message using the caesar cipher
def decrypt(ciphertext)
  #make sure the ciphertext is in uppercase
  ciphertext.upcase!
  plaintext = ""

  #fill in the plaintext with mapping information in the caesar_map
  ciphertext.split("").each do |c|
    plaintext += $caesar_map.index c
  end

  #print the decrypted plaintext
  puts "\n ciphertext: #{ciphertext}\n plaintext: #{plaintext}\n\n"
end

#start the program
init()
I'd initialize with something closer to this (although I might inline the two arrays):

plain_alphabet = ('a'..'z').to_a
cipher_alphabet = ('A'..'Z').to_a.rotate KEY
$caesar_map = Hash[plain_alphabet.zip cipher_alphabet]


The en/decryption (which could likely be handled by the built-in tr method) might look more like:

plaintext.split("").inject("") {|s, c| s &lt;&lt; $caesar_map[c]}


I'd put the whole thing in a class, too; skip the global.