我自学Ruby,一个任务就是制作凯撒密码。 使用#gsub,我已经能够将我的字母更改为整数(' c' => 2),移位它们,然后将新整数更改为字符串(2 =>&#34 ; 2"。)
我碰壁了,Ruby文档没有帮助。当我尝试#gsubs字符串回到字母(" 2" =>' c')时,它只识别0-9。之后的所有内容只是这些数字的串联(" 12" =>' bc'而不是=>' l')。
为什么Ruby会这样做,我该如何解决?
感谢您的帮助。
代码:(我知道它粗糙的初学者代码;我会在通过后尝试编辑它)
def convert_to_integer
puts "What would you like to encode?"
words = gets.chomp
words = words.split("")
words.map { |words| words.gsub!(/[a-z]/, 'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5, 'g' => 6, 'h' => 7, 'i' => 8, 'j' => 9, 'k' => 10, 'l' => 11, 'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17, 's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23, 'y' => 24, 'z' => 25)
}
integer = words.map! { |letter| letter.to_i }
return integer
end
def shift_left(integer, number = 0)
puts "How many letters (to the left) would you like to shift it?"
number = gets.to_i
integer.map! { |n| n - number }
return integer
end
def convert_to_letter(integer)
integer.map! { |integer| integer.to_s }
integer.map! { |n| n.gsub(/[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 , 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]/, '0' => 'a', '1' => 'b', '2' => 'c', '3' => 'd', '4' => 'e', '5' => 'f', '6' => 'g', '7' => 'h', '8' => 'i', '9' => 'j', '10' => 'k', '11' => 'l', '12' => 'm', '13' => 'n', '14' => 'o', '15' => 'p', '16' => 'q', '17' => 'r', '18' => 's', '19' => 't', '20' => 'u', '21' => 'v', '22' => 'w', '23' => 'x', '24' => 'y', '25' => 'z')
}
print integer
end
convert_to_letter(shift_left(convert_to_integer))
答案 0 :(得分:2)
你不需要在那里做gsub
。 gsub
通常用于替换较大字符串的部分。你想要取代整个事情。
这应该可以解决问题:
def convert_to_letter(integers)
replacements = {0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd', 4 => 'e',
5 => 'f', 6 => 'g', 7 => 'h', 8 => 'i', 9 => 'j', 10 => 'k',
11 => 'l', 12 => 'm', 13 => 'n', 14 => 'o', 15 => 'p', 16 => 'q',
17 => 'r', 18 => 's', 19 => 't', 20 => 'u', 21 => 'v', 22 => 'w',
23 => 'x', 24 => 'y', 25 => 'z'
}
integers.map{|x| replacements[x]}.join
end
另外,请注意破坏性操作(map!
此处)。您可能会遇到不希望的副作用(例如,当您认为某些阵列不应该改变时,某些阵列会发生变化。)
答案 1 :(得分:1)
使用查找更容易,更快捷:
@letter_to_number = ('a'..'z').zip(0..25).to_h
@number_to_letter = (0..25).zip('a'..'z').to_h
def convert_to_integers(letters)
letters.map{|l| @letter_to_number[l]}
end
def convert_to_letters(numbers)
numbers.map{|n| @number_to_letter[n]}
end
还有一个快捷方式,它结合了查找并组合了方法。
@convert = (('a'..'z').zip(0..25) + (0..25).zip('a'..'z')).to_h
def convert(objects)
objects.map{|o| @convert[o]}
end
答案 2 :(得分:0)
这不是正则表达式的工作方式。 "12".gsub(/[12]/, '12' => 'm')
不会产生"m"
。该代码表示发现任何“1”或“2”的出现,并根据以下规则替换它:“12”被替换为“m”,并且隐含地,其他任何内容都被替换为空。 “1”和“2”都出现“1”或“2”,但它们都不是“12”,因此它们都被替换为空。因此,上述结果只是空字符串。
实际上gsub
和正则表达式并不是这个问题的理想选择。你可以这样做:
def char_to_int(char)
char.ord - 97
end
def int_to_char(int)
(int + 97).chr
end
def caesar(string, shift)
string.split(" ").map do |word|
word.split("").map do |letter|
int_to_char((char_to_int(letter) - shift) % 26)
end.join
end.join(" ")
end