0

I have this question. Using the Ruby language, have the function CaesarCipher(str,num) take the str parameter and perform a Caesar Cipher shift on it using the num parameter as the shifting number. A Caesar Cipher works by shifting each letter in the string N places down in the alphabet (in this case N will be num). Punctuation, spaces, and capitalization should remain intact. For example if the string is "Caesar Cipher" and num is 2 the output should be "Ecguct Ekrjgt".

Any my code looks like this. I think the onlt problem i have is to update each letter and then each word within the loops. please help. thank you

def Caesar_cipher(str, num)
  if num > 25
    num -= 26
  end
  alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
  str = str.split(" ")
  str.each do |word|
    word.each_char do |c|
      if alphabet.include?(c)
        n = alphabet.index(c) + num
        if n > 25
          n -= 26
        end
        c = alphabet[n]
      end
    end
  end
  return str
end

puts Caesar_cipher("zabcd", 1) // "zabcd"
4
  • c = alphabet[n] doesn't update the character, it just assigns to a local variable c that is never used. Commented Oct 13, 2014 at 12:48
  • You do not update str so can't expect it would contain the result. Enumerator#each* family methods return containing object, no block results. You may look for Enumerable#collect (#map) methods. Also condition to keep n in 0-25 boundary can be simply rewritten with modulo, like n %= 26. Commented Oct 13, 2014 at 12:53
  • You are right. I used map and it worked thanks. Commented Oct 13, 2014 at 12:57
  • Actually, I got it working with minor changes. Noticed some oddities: lowercase letters are not affected, splitting on spaces is not necessary (spaces are not in the alphabet, but block should be modified to return c in this case), use of each_char (could be chained like each_char.collect ... .join for gathering results). Shall I report my findings in more depth, or you'll figure this on your own? Commented Oct 13, 2014 at 13:03

2 Answers 2

1
  str = str.split("")
  alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
  alphabet2 = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
  while num > 25 
    num -= 26
    end

  str = str.map do |char|
    if alphabet.include?(char)
      n = alphabet.index(char) + num
      while n > 25
        n -= 26
        end
      char = alphabet[n]

     elsif alphabet2.include?(char)
       m = alphabet2.index(char) + num



      while m > 25
        m -= 26
        end
      char = alphabet2[m]
      else
       char

     end
    char
    end

  return str.join


end
Sign up to request clarification or add additional context in comments.

3 Comments

This suffers from the same issue I mentioned above: it doesn't affect uppercase letters.
I know, it doesn't. I was focusing on the main problem. sorry for not being detailed. It is updated now.
@TesfaZelalem you can use String#tr to replace characters, e.g.: "caesar cipher".tr(alphabet.join, alphabet.rotate(2).join)
1
def cipher_shift(s, n)
  letters = [*'a'..'z'] 
  s.chars.map {|x| letters.include?(x.downcase) ? (x.ord + n).chr : x}.join
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.