3

Suppose the character string is "abc" and user input is 3 then the output becomes "def".

Every character is supposed to be increased by the user input as integer value.

I wrote a code but it is giving an error. Is there any other way to do this?

#!/usr/bin/ruby -w

puts "Enter the value of n";
$n=gets;
s = String.new("abc");
s.split("").each do |i|
    $j = 0;
    x = i;
    begin
         x.next;
         $j = $j + 1;
    end while $j < $n

    puts x;
end
6
  • Should << be <? Commented Mar 31, 2018 at 15:35
  • yes @SebastianPalma i just edited. Commented Mar 31, 2018 at 15:54
  • @SebastianPalma i also tried ( i.ord + n).chr to directly convert a to d avoiding x.next but this is also giving error - in `+': String can't be coerced into Fixnum (TypeError) Commented Mar 31, 2018 at 16:06
  • See ganesh's answer. Try parsing the user's input to integer $n=gets.to_i. See the repl. Commented Mar 31, 2018 at 16:07
  • Have you considered the desired output for the strings whose +n characters fall off the alphabet e.g. 'xyz' etc? Commented Mar 31, 2018 at 17:46

3 Answers 3

5

There are several things to add in your code:

  • Instead String.new, you can simply add your string within quotes.
  • str.split("") can be str.chars.
  • $j = $j + 1 can be $j += 1.
  • If you're doing a comparison between $j and $n then << should be <.
  • You don't need ; unless you're writing all in one line.
  • begin; end while can be just while; end

I guess it could be like:

n = gets.to_i
s = 'abc'
s.split('').each do |i|
  j = 0
  x = i
  while j < n
    x = x.next
    j += 1
  end
  puts x
end

But you could use String#ord over each char in your string to return the ordinal of it, add the user input and then String#chr to get the ASCII character for that number:

# With n being the user's input as integer, in this case 3.
p 'abc'.chars.map { |char| (char.ord + n).chr }.join 
# "def"

Added n = gets.to_i as stated in the comments by @Ganesh.

If looking for a Caesar Cipher implementation:

def foo(string, n)
  lower = ('a'..'z').to_a.join
  upper = ('A'..'Z').to_a.join
  string.tr(lower + upper, lower[n..-1] + lower[0...n] + upper[n..-1] + upper[0...n])
end

p foo('XYZ', 1) # "YZA"
p foo('ABC', 1) # "BCD"
p foo('ABC', 3) # "DEF"

Slower, but...

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

9 Comments

Thanks for this answer. Actually one error is disturbing:in `<': comparison of Fixnum with String failed (ArgumentError) . This is happening whenever i am scanning the value of n.. ie by n=gets
It's strange, since j and n are always numbers, what's the code you're trying with?
I used the same code u have suggested this time: but j and n aren't been compared. in `<': comparison of Fixnum with String failed (ArgumentError) this error is encountered.
See the working code here, is yours implemented the same way?
What does this return if you have ‘xyz’ and n = 1?
|
4

You can use tr and rotate. Assumes you want a circular-mapping i.e. 'z' => 'a' for a +1 map.

def caesar str, n
  str.tr 'a-z', [*'a'..'z'].rotate(n).join
end

caesar 'abc', 3 #=> 'def'
caesar 'xyz', 3 #=> 'abc'

See docs for info on these methods.

1 Comment

Have just noticed this answer is almost identical to one in a comment by Stefan to another q&a.
2

If all characters are lower-case ASCII letters:

def caesar(str, n)
  base = 'a'.ord
  str.gsub(/./) { |c| (base + (c.ord+n-base) % 26).chr }
end

str = "abcxyza"
caesar(str,  1) #=> "bcdyzab"
caesar(str,  2) #=> "cdezabc"
caesar(str, 25) #=> "zabwxyz"
caesar(str, 26) #=> "abcxyza"

If all characters are ASCII letters:

def caesar(str, n)
  str.gsub(/./) do |c|
    base = (c==c.upcase ? 'A' : 'a').ord
    (base + (c.ord+n-base) % 26).chr
  end
end

str = "AbcDefXyZa"
caesar(str,  1) #=> "BcdEfgYzAb"
caesar(str,  2) #=> "CdeFghZaBc"
caesar(str, 25) #=> "ZabCdeWxYz"
caesar(str, 26) #=> "AbcDefXyZa"

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.