3

I am attempting to create a Caesar Cipher in Ruby for my computer science class. My friend was able to create part of the code:

def cipher(word, n)
new_word = ""
word.each_char do |i|
    n.times do
        if(i == "z")
            i = "a"
            next
        elsif(i == "Z")
            i = "A"
            next
        end
        i.next!
        i == "%" ? i = " " : ""
    end
    new_word += i   
end
puts new_word
end
cipher("phrase", 5)

Where the last line is where you would put the phrase you want to scramble, and the number is how much you want to scramble it by. One of the requirements is that we use gets.chomp to specify a phrase and amount to scramble by without editing the .rb file itself. So I came up with this:

puts "What would you like to scramble?"
word = gets.chomp
puts "How much would you like to scramble that?"
n = gets.chomp
def cipher(word, n)
new_word = ""
word.each_char do |i|
    n.times do
        if(i == "z")
            i = "a"
            next
        elsif(i == "Z")
            i = "A"
            next
        end
        i.next!
        i == "%" ? i = " " : ""
    end
    new_word += i   
end
puts new_word
end
cipher(word, n)

And I get the following error outputed when run in Terminal:

some.rb:10:in `block in cipher': undefined method `times' for "5":String (NoMethodError)
from some.rb:9:in `each_char'
from some.rb:9:in `cipher'
from some.rb:26:in `<main>'

If someone could help me figure out what I'm doing wrong, that would help me out a lot.

4 Answers4

1

Call .to_i on n.

You need to convert that string you got from the user's input into a number before you can run .times on it. .to_i does this for you.

Example: http://progzoo.net/wiki/Ruby:Convert_a_String_to_a_Number

Patrick Stephen
  • 325
  • 1
  • 8
1

Did this a while ago, the requirements were only lowercase ASCII alphabet letters, hope you get the general idea to do it your way:

def encrypt(msg, key)
    msg.downcase.split("").each_with_index do |char, i|
        next if msg[i] == " "
        msg[i] = (msg[i].ord + key) > 122 ? (((msg[i].ord + key) % 123) + 97).chr : (msg[i].ord + key).chr
    end
    msg
end

def decrypt(msg, key)
    msg.downcase.split("").each_with_index do |char, i|
        next if msg[i] == " "
        msg[i] = (msg[i].ord - key) < 97  ? (123 - (97 - (msg[i].ord - key))).chr : (msg[i].ord - key).chr
    end
    msg
end
acib708
  • 1,573
  • 1
  • 13
  • 24
1

gets.chomp returns a string

word = gets.chomp

So word is a string, as expected, but then you call gets.chomp again, this time to get number of scrabbles that should be applied to the string. So n is a string as well.

n = gets.chomp

When you call the times method on n it's not defined, because it only makes sense on integers. The solution is to convert n to an integer. This should work:

n = gets.chomp.to_i

Update

Documentation on the to_i method on String instances: http://ruby-doc.org/core-2.0.0/String.html#method-i-to_i

Stratus3D
  • 4,648
  • 4
  • 35
  • 67
1

gets.chomp return a string, you must convert it to a number in order to call .times method. Change this line n = gets.chomp by n = gets.chomp.to_i

leobelizquierdo
  • 1,648
  • 12
  • 20