如何将电话簿号码转换为字母[关闭]
Posted
技术标签:
【中文标题】如何将电话簿号码转换为字母[关闭]【英文标题】:How to convert telephone pad numbers to letters [closed] 【发布时间】:2020-06-23 22:48:02 【问题描述】:我正在尝试编写代码来模拟使用 Ruby 中的multi-tap 电话键盘编写文本消息。这是电话键盘:
1 2 3
ABC DEF
4 5 6
GHI JKL MNO
7 8 9
PQRS TUV WXYZ
0
(space)
我尝试在 Ruby 中将其定义为:(不起作用)
"0" = [" "] # (adds a space)
"1" = [""] # (adds nothing)
"2" = ["a", "b", "c"]
"3" = ["d", "e", "f"]
"4" = ["g", "h", "i"]
"5" = ["j", "k", "l"]
"6" = ["m", "n", "o"]
"7" = ["p", "q", "r", "s"]
"8" = ["t", "u", "v"]
"9" = ["w", "x", "y", "z"]
我将通过两个示例来解释它是如何工作的。首先我将发送字符串goat
。要发送g
,我按4 一次。接下来,要发送o
,我按6 三次(因为按6 一次将发送m
,按6 两次将发送@ 987654331@)。对于a
,按一次2,对于t
,按一次8。因此我们会发送
466628
g oat
接下来,考虑cake
。通过相同的程序,我们将发送
22225533
ca k e
这里有问题。解码时,2222 有几种可能性。可能是aaaa
、bb
等等。为了克服这种歧义,在每个数字字符串之后插入一个表示为空格的“暂停”,然后是相同数字的字符串。因此,对于cake
,我们会写
222 25533
c a k e
我已经有了一个带有数字及其对应字母的散列,而且我知道我必须按照数字重复的次数对数字进行排序。 但我不知道我用什么方法。
另外,如果我需要编码(数字到字母),我是否必须使用相同的逻辑?
【问题讨论】:
请查看“How to Ask”、“Stack Overflow question checklist”及其所有链接页面。我们希望看到您尝试解决此问题。目前,您已经向我们提出了您应该解决的要求,并希望我们为您编写代码。 “How do I ask and answer homework questions?”会解释。 @CarySwoveland 这是一个暂停,所以222
可以注册为c
。如果没有空格,2222
可以是 aaaa
、aab
、aba
、ac
或任何其他组合。
g13,我相信@Stefan 和我所做的编辑与您尝试做的一致。如果是这样,您可能希望澄清最后一句话,这是您的原话。如果您澄清该句子以说明您希望仅对文本进行编码,或者同时对文本进行编码和解码,则有可能会重新打开该问题。这是一个有趣的问题。
你好@CarySwoveland 和@Stefan!对不起,我花了太长时间,我已经做了很长时间的这些作业,所以我决定花一些时间离开电脑,不久前回来了。我测试了编码和解码解决方案,它们都有效。它鼓励我更深入地研究正则表达式和地图,它帮助我解决了其他作业!非常感谢您花时间帮助我。当我有另一个问题时,我会更加小心。现在我将根据我在此处寻求帮助时取得的进展对其进行编辑。
【参考方案1】:
(当 Cary Swoveland 指出你可能想要解码时,我先有编码部分。现在答案包含两种方式并且变得很长,我希望你不介意)
您的示例代码不起作用。您不能只分配给字符串文字。但是,您可以使用这样的哈希值在 Ruby 中定义您的键盘:
keypad =
'0' => [' '],
'1' => [], # <- you can leave this out
'2' => %w[a b c],
'3' => %w[d e f],
'4' => %w[g h i],
'5' => %w[j k l],
'6' => %w[m n o],
'7' => %w[p q r s],
'8' => %w[t u v],
'9' => %w[w x y z],
解码
要将222 25533
转换为cake
,我首先要拆分连续的以空格分隔的数字。您可以使用正则表达式:
parts = '222 25533'.gsub(/(\d)\1*/).map(&:itself)
#=> ["222", "2", "55", "33"]
这可以转换为包含键/次数对的数组:
key_strokes = parts.map |part| [part[0], part.length]
#=> [["2", 3], ["2", 1], ["5", 2], ["3", 2]]
可以使用keypad
哈希转换为字母:
letters = key_strokes.map |key, times| key_pad[key][times - 1]
#=> ["c", "a", "k", "e"]
需要- 1
,因为数组索引是从零开始的。最后,把字母变成单词:
letters.join
#=> "cake"
编码
要将字符转换为击键,我会创建一个基于键盘的哈希,它将每个字符映射到一个键/次数对:
mapping =
key_pad.each do |key, values|
values.each.with_index(1) do |char, times|
mapping[char] = [key, times]
end
end
mapping
#=>
# " "=>["0", 1], "a"=>["2", 1], "b"=>["2", 2], "c"=>["2", 3], "d"=>["3", 1],
# "e"=>["3", 2], "f"=>["3", 3], "g"=>["4", 1], "h"=>["4", 2], "i"=>["4", 3],
# "j"=>["5", 1], "k"=>["5", 2], "l"=>["5", 3], "m"=>["6", 1], "n"=>["6", 2],
# "o"=>["6", 3], "p"=>["7", 1], "q"=>["7", 2], "r"=>["7", 3], "s"=>["7", 4],
# "t"=>["8", 1], "u"=>["8", 2], "v"=>["8", 3], "w"=>["9", 1], "x"=>["9", 2],
# "y"=>["9", 3], "z"=>["9", 4]
#
在上面的哈希中,"c"=>["2", 3]
表示要获得c
,您必须按 2 键 3 次。要在 Ruby 中呈现单个键的序列,我们可以使用重复字符串的 String#*
:
key, times = mapping['c']
key #=> '2'
times #=> 3
key * times
#=> '222'
获取整个单词(或句子)的击键是将每个字符映射到其各自的哈希值:
parts = 'cake'.each_char.map |char| mapping[char]
#=> [["2", 3], ["2", 1], ["5", 2], ["3", 2]]
要渲染实际序列,我们必须首先对同一键的连续运行进行分组:
chunks = parts.chunk_while |(a, _), (b, _)| a == b .to_a
#=> [
# [["2", 3], ["2", 1]],
# [["5", 2]],
# [["3", 2]]
# ]
我们现在可以通过空格和没有空格的块连接相同的击键:
chunks.map |chunk| chunk.map |k, t| k * t .join(' ') .join
#=> "222 25533"
【讨论】:
我会在早上回来查看,但请看一下问题的最后一句话(我没有触及)。它向我表明,OP 可能想要解码而不是(或除了)编码。如果您有时间,您可能想在任何情况下进行解码。我 @CarySwoveland 你可能是对的,我完全忽略了这一点! (将其添加到我的答案中) @CarySwoveland 好点,但是这个答案已经花了太长时间了,我将把它作为“给读者的练习” :-)【参考方案2】:给你:
arr = [
["0", [" "]],
["1", [""]],
["2", ["a", "b", "c"]],
["3", ["d", "e", "f"]],
["4", ["g", "h", "i"]],
["5", ["j", "k", "l"]],
["6", ["m", "n", "o"]],
["7", ["p", "q", "r", "s"]],
["8", ["t", "u", "v"]],
["9", ["w", "x", "y", "z"]]
]
我一直对包含以下内容感到困惑
["1", [""]],
这似乎没有任何用处。但是,如果不是
222 25533
我们用"cake"
来表示字符串
222125533
也就是说,如果由相同数字的字符串表示的两个连续字符(例如"222"
和"2"
)它们将由"1"
分隔,而不是由“暂停”,表示作为空间。如果这样做了,我们可以如下编码和解码字符串。
编码
CHAR_TO_DIGITS = arr.each_with_object() do |(num, a),h|
a.each.with_index(1) |ltr,i| h[ltr] = num * i
end
#=> " "=>"0", ""=>"1", "a"=>"2", "b"=>"22", "c"=>"222",
# "d"=>"3", "e"=>"33", "f"=>"333", "g"=>"4", "h"=>"44",
# "i"=>"444", "j"=>"5", "k"=>"55", "l"=>"555", "m"=>"6",
# "n"=>"66", "o"=>"666", "p"=>"7", "q"=>"77", "r"=>"777",
# "s"=>"7777", "t"=>"8", "u"=>"88", "v"=>"888", "w"=>"9",
# "x"=>"99", "y"=>"999", "z"=>"9999"
def encode(plain_text)
plain_text.each_char.with_object('') do |c,s|
digits = CHAR_TO_DIGITS[c]
s << '1' if !s.empty? && digits[0] == s[-1]
s << digits
end
end
然后
encoded_1 = encode "cake"
#=> "222125533"
encoded_2 = encode "my dog has fleas"
#=> "69990366640442777703335553327777"
解码
解码更容易。
DIGITS_TO_CHAR = CHAR_TO_DIGITS.invert
#=> "0"=>" ", "1"=>"", "2"=>"a", "22"=>"b", "222"=>"c",
# "3"=>"d", "33"=>"e", "333"=>"f", "4"=>"g", "44"=>"h",
# "444"=>"i", "5"=>"j", "55"=>"k", "555"=>"l", "6"=>"m",
# "66"=>"n", "666"=>"o", "7"=>"p", "77"=>"q", "777"=>"r",
# "7777"=>"s", "8"=>"t", "88"=>"u", "888"=>"v", "9"=>"w",
# "99"=>"x", "999"=>"y", "9999"=>"z"
def decode(encoded_text)
encoded_text.gsub(/(\d)\1*/, DIGITS_TO_CHAR)
end
然后
decode encoded_1
#=> "cake"
decode encoded_2
#=> "my dog has fleas"
这使用String#gsub 的形式,它使用散列来进行替换。另见Hash#invert。
【讨论】:
【参考方案3】:我首先将“222 25533”转换为数组[[2,3],[2,1],[5,2],[3,2]]
,其中第一个数字代表一个数字,第二个数字是它的出现次数。
有了这个,你可以很容易地从键盘上找到字母。
【讨论】:
以上是关于如何将电话簿号码转换为字母[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
结帐后如何将摩洛哥国家代码添加到 wp woocommerce 中的电话号码? [关闭]
如何在电话号码格式的范围内生成随机数 Postman [关闭]