lib/shift_cipher/caesar.rb in shift_cipher-1.0.0 vs lib/shift_cipher/caesar.rb in shift_cipher-1.1.0

- old
+ new

@@ -1,80 +1,67 @@ module ShiftCipher class Caesar - attr_accessor :offset + DEFAULT_OFFSET = 0 - def initialize(start = 0) + FIRST_UNICODE_CODEPOINT = 97 + LAST_UNICODE_CODEPOINT = 123 - # set default - @offset = 0 + attr_accessor :offset - # have we got a string? - if start.respond_to?(:ord) - - # is it alphabetic? - if ('A'..'Z').include?(start) - @offset = start.downcase.ord - 97 - elsif ('a'..'z').include?(start) - @offset = start.ord - 97 - - # is it numeric & in range? - elsif (1..26).include?(start.to_i.abs) - @offset = start.to_i - end - - # have we got a number - elsif start.respond_to?(:to_i) - # is it in range? - if (1..26).include?(start.to_i) - @offset = start.to_i - end - end - - # raise an error ... - # what about case when start set to 0? + def initialize(start = 0) + @offset = calculate_offset(start) end def encrypt(message) - shift(message, @offset) + shift(message, offset) end def decrypt(message) - shift(message, - @offset) + shift(message, -offset) end private + def shift(message, directional_offset) - shifted_message = "" - message.downcase.split("").each do |character| + return unless message + + message.downcase.split("").map do |character| if is_alpha?(character) - shifted_character = shift_character(character, directional_offset) - shifted_message += shifted_character - elsif is_numeric?(character) #or is_whitespace?(character) - shifted_message += character + character_for(character.ord + directional_offset) + elsif is_numeric?(character) + character end - end if message - shifted_message.squeeze(' ') + end.join("").squeeze(" ") end + def calculate_offset(character) + if ("A".."z").include?(character) + character.downcase.ord - FIRST_UNICODE_CODEPOINT + elsif (0..26).include?(character.to_i.abs) + character.to_i + else + DEFAULT_OFFSET + end + end + def is_alpha?(character) character.match(/^[[:alpha:]]$/) end def is_numeric?(character) character.match(/^[[:digit:]]$/) end - def is_whitespace?(character) - character.match(/^\s$/) - end - - def shift_character(character, offset) - shifted_ord = character.ord + offset - if shifted_ord < 97 - shifted_ord = 123 - (97 - shifted_ord) - elsif shifted_ord > 122 - shifted_ord = 97 + (shifted_ord - 123) + # Given the shifted order for a char, returns the corresponding character + # If the offset takes us past 123 ('z'), we wrap around to 97 ('A') + # + # Returns Char + def character_for(unicode_codepoint) + if unicode_codepoint < FIRST_UNICODE_CODEPOINT + unicode_codepoint = LAST_UNICODE_CODEPOINT - (FIRST_UNICODE_CODEPOINT - unicode_codepoint) + elsif unicode_codepoint >= LAST_UNICODE_CODEPOINT + unicode_codepoint = FIRST_UNICODE_CODEPOINT + (unicode_codepoint - LAST_UNICODE_CODEPOINT) end - shifted_ord.chr + unicode_codepoint.chr end end -end \ No newline at end of file +end