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