0

我正在研究左移为 1 的凯撒密码问题,但入门有困难。提示要求我查看 Ruby 文档中的 String 方法 #ord 和 Integer 方法 #chr。并且字母'a'必须转移到'z'......

下面是我的作品。。

def solve_cipher(string, n)
letters = ['a'..'z']
string.map {|x| letters.include?(x.ord + n).chr : x}.join

感谢您的任何建议...!

4

3 回答 3

0

首先,您应该使用模运算符来保持在letters范围内。其次,您试图以错误的方式使用条件运算符 - 阅读有关三元运算符的信息。将字符更改为letters数组中的数字并将其移出函数也将是一种改进。另一个问题是RubyString中没有方法map。您必须使用chars方法,该方法返回字符串中的字符数组。

solve_cipher您的功能的修改版本:

LETTERS = ('a'.ord..'z'.ord)

def solve_cipher(string, n)
  string.chars.map {|x| LETTERS.include?(x.ord)?((x.ord - LETTERS.min + n) % 26 + LETTERS.min).chr  : x}.join
end

如您所见,我将除以数组26长度后的余数LETTERS保持在小写字母的范围内。.

于 2015-08-02T21:31:05.830 回答
0

你需要把split你的话变成单个字符。然后您需要将字符转换为整数,ord以便您可以进行算术运算。算术运算是添加一个相对于“a”的偏移量,以 26 为模,以便结果映射到与“a”不同的偏移量,这将产生一个新字符。用 将结果改回字符chr,然后将字符重新连接在一起形成一个字符串。

这是一种可能的实现,它同时容纳大写和小写字母:

def shift_char(c, base, offset)
  (((c.ord - base) + offset) % 26 + base).chr
end

def cipher(s, offset)
  s.chars.map do |c|
    case c
    when 'a'..'z'
      shift_char(c, 'a'.ord, offset)
    when 'A'..'Z'
      shift_char(c, 'A'.ord, offset)
    else
      c
    end
  end.join
end

cipher_text = cipher('Now is the time for all good men...', 13)
p cipher_text       # "Abj vf gur gvzr sbe nyy tbbq zra..."
original_text = cipher(cipher_text, 13)
p original_text     # "Now is the time for all good men..."
于 2015-08-02T21:38:09.327 回答
-1

您可能正在寻找这样的东西:

def solve_cipher(string, n)
  string.split('').map do |x|
    new_index = x.ord + n
    while new_index > 'z'.ord
      new_index = 'a'.ord + new_index - 'z'.ord - 1
    end
    if new_index < 'a'.ord
      new_index = 'z'.ord - ('a'.ord - new_index) + 1
    end
    new_index.chr
  end.join
end
于 2015-08-02T21:31:12.003 回答