06-电话号码助记符
9.3 电话号码助记符
在内置通讯录的智能手机出现之前,电话机数字键盘的每个按键上都带有字母。这些字母是为了提供简单的助记符,以便记住电话号码。在美国,通常数字键1上不带字母,2上是ABC,3上是DEF,4上是GHI,5上是JKL,6上是MNO,7上是PQRS,8上是TUV,9上是WXYZ,0上不带字母。例如,1-800-MY-APPLE对应于电话号码1-800-69-27753。在广告中偶尔还会出现这些助记符,因此键盘上的数字已经带入了现代智能手机应用程序中,如图9-4所示。

如何为某个电话号码想出一个新的助记符呢?在20世纪90年代,有一些流行的共享软件可以帮助完成这项工作。这些软件会生成电话号码各字母的每种排列,并查字典找出排列中包含的单词。然后会向用户显示带有最完整单词的排列。这里将完成问题的上半部分。查字典的部分将会留作习题。
在上述最后一个问题中,在研究排列的生成方式时用到了 permutations() 函数,以便生成旅行商问题的可能路径。但正如前所述,生成排列的方法有很多。特别是对本问题而言,我们不会交换现有排列中两个值的位置来生成新的排列,而是会从头开始生成每个排列。与电话号码中每个数字可能匹配的字母都会被检索,并随着后续数字的读入而不断加入更多的可能匹配值。此操作仍然是一种笛卡儿积,Python标准库的 itertools 模块已经包含了这个功能。
首先,我们定义一下数字和可能匹配字母的映射关系,具体代码如代码清单9-8所示。
代码清单9-8 tsp.py(续)
from typing import Dict, Tuple, Iterable, List
from itertools import product
phone_mapping: Dict[str, Tuple[str, ...]] = {"1": ("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"),
"0": ("0",)}
下一个函数将对给定电话号码的每个数字生成所有可能的组合,形成可能的助记符列表。先为电话号码中的每个数字创建可能的字母元组列表,然后通过 itertools 模块中的笛卡儿积函数 product() 来实现。请注意,这里用到了解包运算符 * ,将 letter_tuples 中的元组用作 product() 的参数。具体代码如代码清单9-9所示。
代码清单9-9 tsp.py(续)
def possible_mnemonics(phone_number: str) -> Iterable[Tuple[str, ...]]:
letter_tuples: List[Tuple[str, ...]] = []
for digit in phone_number:
letter_tuples.append(phone_mapping.get(digit, (digit,)))
return product(*letter_tuples)
现在可以为某个电话号码找出所有可能的助记符了,具体代码如代码清单9-10所示。
代码清单9-10 tsp.py(续)
if __name__ == "__main__":
phone_number: str = input("Enter a phone number:")
print("Here are the potential mnemonics:")
for mnemonic in possible_mnemonics(phone_number):
print("".join(mnemonic))
结果就是电话号码1440787也可以写成1GH0STS。这好记多了。