Skip to content

Instantly share code, notes, and snippets.

@waysidekoi
Last active August 29, 2015 13:57
Show Gist options
  • Save waysidekoi/9401953 to your computer and use it in GitHub Desktop.
Save waysidekoi/9401953 to your computer and use it in GitHub Desktop.
Vigenere cipher (source: http://www.problemotd.com/)
Vigenere cipher
The Vigenere cipher made its rounds in the mid-1550s up until the end of the American Civil War.
It was very easy for soldiers to encode messages and pass them around to all the allied camps. It
was very easy for soldiers to encode messages and pass them aroudn to all the allied camps.
The cipher requires a key and a message. It works like this:
Key:
REDDIT
Message:
TODAYISMYBIRTHDAY
REDDITREDDITREDDI
TODAYISMYBIRTHDAY
-----------------
KSGDGBJQBEQKKLGDG
Using a 0 based alphabet (A=0), R is the 17th letter of the alphabet and T is the 19th letter
of the alphabet. (17 + 19) mod 26 = 11 which is where K resides in the alphabet. Repeat for each
key/message letter combination until done.
Today's problem of the day is two part. The first part is to implement a Vigenere cipher in the
programming language of your choice. Feel free to post solutions or links to solutions in the
comments.
The second part is to try and implement something to crack the message below (the key is 5 or less
characters).
ZEJFOKHTWHCGAW
Good Luck!
# Part 1
class Cipher
attr_reader :key, :msg
def initialize(key, msg)
@key = key
@msg = msg
end
def index_position(char)
alphabet = ('A'..'Z').to_a
alphabet.index(char)
end
def character_at(position)
alphabet = ('A'..'Z').to_a
alphabet[position]
end
def encrypt
result = []
zipped_msg = combine
zipped_msg.each do |pair|
code_position = (index_position(pair[0]) + index_position(pair[1])) % 26
result << character_at(code_position)
end
result.join
end
def combine
# expand key to match length of message
expanded_key = key * msg.length.fdiv(key.length).ceil
# turn key into array to pop extras
expanded_key = expanded_key.split(//)
# calc how many extra chars exist
key_muffintop = expanded_key.length - msg.length
# match message length
expanded_key.pop(key_muffintop)
# convert msg to array
expanded_msg = msg.split(//)
expanded_key.zip(expanded_msg)
end
end
key = 'reddit'.upcase
message = 'TODAYISMYBIRTHDAY'.upcase
cipher = Cipher.new(key, message)
p cipher.encrypt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment