Created
February 16, 2010 02:50
-
-
Save frogandcode/305242 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'test/unit' | |
# Note: Encrypted strings used to validate the tests below code were generated at: | |
# http://www.braingle.com/brainteasers/codes/caesar.php | |
# So if the tests pass, they either validate my code or we both have the same bugs :) | |
class CaesarCipherTest < Test::Unit::TestCase | |
QUICK_BROWN_FOX = "the quick brown fox jumps over the lazy dog" | |
QUICK_BROWN_FOX_SHIFT_3 = "wkh txlfn eurzq ira mxpsv ryhu wkh odcb grj" | |
DEAR_BRUTUS = "The fault, dear Brutus, lies not in our stars but in ourselves." | |
def test_encrypt | |
assert_equal QUICK_BROWN_FOX_SHIFT_3, CaesarCipher.encrypt(QUICK_BROWN_FOX) | |
end | |
def test_encrypt_uppercase_string_produces_upper_case_result | |
assert_equal QUICK_BROWN_FOX_SHIFT_3.upcase, CaesarCipher.encrypt(QUICK_BROWN_FOX.upcase) | |
end | |
def test_encrypt_with_non_default_shift | |
encrypted_shift_8 = "bpm ycqks jzwev nwf rcuxa wdmz bpm tihg lwo" | |
assert_equal encrypted_shift_8, CaesarCipher.encrypt(QUICK_BROWN_FOX, 8) | |
end | |
def test_encrypt_with_negative_shift | |
encrypted_shift_minus_8 = "lzw imauc tjgof xgp bmehk gnwj lzw dsrq vgy" | |
assert_equal encrypted_shift_minus_8, CaesarCipher.encrypt(QUICK_BROWN_FOX, -8) | |
end | |
# Just in case we rigged our impl for the quick brown fox and lazy dog | |
def test_encrypt_different_string_with_mixed_case | |
brutus_shift_19 = "Max ytnem, wxtk Uknmnl, ebxl ghm bg hnk lmtkl unm bg hnklxeoxl." | |
assert_equal brutus_shift_19, CaesarCipher.encrypt(DEAR_BRUTUS, 19), "should preserve case" | |
end | |
def test_decrypt | |
assert_equal QUICK_BROWN_FOX, CaesarCipher.decrypt(QUICK_BROWN_FOX_SHIFT_3) | |
end | |
def test_decrypt_uppercase_string_produces_upper_case_result | |
assert_equal QUICK_BROWN_FOX.upcase, CaesarCipher.decrypt(QUICK_BROWN_FOX_SHIFT_3.upcase) | |
end | |
def test_decrypt_with_non_default_shift | |
encrypted_shift_13 = "gur dhvpx oebja sbk whzcf bire gur ynml qbt" | |
assert_equal QUICK_BROWN_FOX, CaesarCipher.decrypt(encrypted_shift_13, 13) | |
end | |
def test_decrypt_different_string_with_mixed_case | |
brutus_shift_17 = "Kyv wrlck, uvri Silklj, czvj efk ze fli jkrij slk ze flijvcmvj." | |
assert_equal DEAR_BRUTUS, CaesarCipher.decrypt(brutus_shift_17, 17) | |
end | |
def test_encrypt_and_decrypt_with_alphabet_size_shift_produce_original | |
assert_equal DEAR_BRUTUS, CaesarCipher.encrypt(DEAR_BRUTUS, 26) | |
assert_equal DEAR_BRUTUS, CaesarCipher.decrypt(DEAR_BRUTUS, 26) | |
end | |
end | |
# Api for applying a simple Caesar Cipher algorithm (http://en.wikipedia.org/wiki/Caesar_cipher) | |
# to encrypt and decrypt strings. | |
class CaesarCipher | |
ALPHABET = ('a'..'z').to_a | |
class << self | |
# Encrypts the string passed, preserving the case of its characters | |
# so that subsequent decryption will read exactly as the original. | |
# Handles positive or negative values for the shift. | |
def encrypt(string, shift=3) | |
string.chars.map {|c| encrypt_char(c, shift)}.to_s | |
end | |
# Decrypts the string passed, preserving the case of its characters. | |
def decrypt(string, shift=3) | |
string.chars.map {|c| decrypt_char(c, shift)}.to_s | |
end | |
protected | |
def encrypt_char(char, shift=3) | |
shift_char(char, shift, true) | |
end | |
def decrypt_char(char, shift=3) | |
shift_char(char, shift, false) | |
end | |
# Returns case-sensitive shift transformation of the character passed if it's a letter, | |
# or the character itself if it's not. Also handles negative shifts. | |
def shift_char(char, shift, shift_forward=true) | |
pos = ALPHABET.index(char.downcase) | |
# If char not in alphabet, simply return it. Handles spaces, punctuation, numbers, etc. | |
return char if pos.nil? | |
shift = (shift < 0) ? shift + ALPHABET.length : shift # Handle negative shift | |
shift_pos_without_mod = shift_forward ? (pos + shift) : (pos - shift) | |
shifted_pos = shift_pos_without_mod % ALPHABET.length | |
shifted_char = ALPHABET[shifted_pos] | |
case_sensitive_char(char, shifted_char) # Keep case of char passed | |
end | |
def case_sensitive_char(input_char, result_char) | |
input_char.downcase == input_char ? result_char : result_char.upcase | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment