小T的密码变换规则
问题描述
小T设计了一套密码变换规则,将输入的字符串转换成一串数字密码。变换规则如下:
- 小写字母按以下映射关系进行转换:
a, b, c->2d, e, f->3g, h, i->4j, k, l->5m, n, o->6p, q, r, s->7t, u, v->8w, x, y, z->9
- 大写字母先转为小写字母,再跳到字母表中的前一个字母,并按上述规则转换为对应的数字。例如,
B转换为a,再转换为2;A特殊处理,先变为Z,再转换为9。 - 非字母字符保持不变。
例如:对于输入字符串 "LIming0701",转换后的数字密码为 5464640701。
解题思路
- 遍历输入字符串的每个字符。
- 对于小写字母,直接从
letter_to_digit字典中获取对应的数字。 - 对于大写字母,先转为小写字母,然后跳到字母表中的前一个字母,再从
letter_to_digit字典中获取对应的数字。 - 对于非字母字符,直接添加到结果列表中。
- 最后,将结果列表中的元素连接成一个字符串并返回。
代码实现
-
初始化映射字典
替换操作的初级方法就是使用if-elif-else语句。但是,写一大长串if-elif-else语句实在是太麻烦了,尤其是26个英文字母,大写+小写一共52个字符,如果用if-elif-else语句,不知道整段代码会写到什么时候。这种情况下,就需要先创建一个字典,再通过
.get()函数取值。根据题目,小写字母的映射关系如下:
a, b, c->2d, e, f->3g, h, i->4j, k, l->5m, n, o->6p, q, r, s->7t, u, v->8w, x, y, z->9
通过这样的映射关系,我们可以创建这样一个字典:
letter_to_digit = { 'a': '2', 'b': '2', 'c': '2', 'd': '3', 'e': '3', 'f': '3', 'g': '4', 'h': '4', 'i': '4', 'j': '5', 'k': '5', 'l': '5', 'm': '6', 'n': '6', 'o': '6', 'p': '7', 'q': '7', 'r': '7', 's': '7', 't': '8', 'u': '8', 'v': '8', 'w': '9', 'x': '9', 'y': '9', 'z': '9' } -
遍历字符&判断字符
首先,创建一个空列表
result,作为存储字符的列表。result = []接下来,使用for循环遍历输入字符串
s的每个字符char,并使用if-elif-else语句对每个字符char进行判断。对于小写字母或大写字母,按题设变换规则进行处理;对于非字母字符,直接使用result.append(char)将原字符添加到结果列表中。for char in s: if char.islower(): #小写字母处理 elif char.isupper(): #大写字母处理 else: result.append(char) -
小写和大写字母的转换
对于小写字母,根据题设变换规则,直接从
letter_to_digit字典中获取对应的数字即可。result.append(letter_to_digit[char])对于大写字母,题设变换规则是“先转为小写字母,再跳到字母表中的前一个字母,并按上述规则转换为对应的数字”。大写字母转小写字母很简单,使用
char.lower()就可以了。而要想实现跳到字母表中的前一个字母这一步骤,需要将转换后的小写字母通过ord()转换为ASCII码,将该ASCII码减去1,再将减法处理后的ASCII码通过chr()函数重新转换为字符。lower_char = chr(ord(char.lower()) - 1)大写字母
'A'对应的ASCII码是41,而ASCII码40所对应的字符是'@';即使将A通过lower()转换为小写字母'a',这个小写字母对应的ASCII码是61,而60对应的字符也已经不是大写或小写字母了。因此,对于大写字母'A',需要进行特殊处理。具体代码实现有以下两种方法:
方法1
if char == 'A': lower_char = 'z' else: lower_char = chr(ord(char.lower()) - 1) result.append(letter_to_digit[lower_char])方法2
if char == 'A': result.append('9') else: lower_char = chr(ord(char.lower()) - 1) result.append(letter_to_digit[lower_char])以上两种替换大写字母的方法,最终返回的结果是相同的。区别在于,前者只是将包括
'A'在内的全部大写字母按部就班地先转为小写字母,然后跳到字母表中的前一个字母,再从letter_to_digit中获取对应的数字;后者将'A'与其他25个大写字母分别处理,直接将'A'替换为'9',省略了“依据题设将'A'替换为'z',再通过查找letter_to_digit替换为'9'”的中间过程。具体过程可参考以下流程图:方法1
flowchart LR 判断字符是否\n为大写字母 -- 大写字母A --> 根据题设转换规则\n转换为小写字母z --> 从字典中查找小写字母\n并转换为对应的数字 --> 将转换后的数字\n添加到结果列表中 判断字符是否\n为大写字母 -- 除A以外的\n25个大写字母 --> 根据题设转换规则\n转换为相应的小写字母 --> 从字典中查找小写字母\n并转换为对应的数字方法2
flowchart LR 判断字符是否\n为大写字母 -- 大写字母A --> 根据题设转换规则\n直接转换为数字9 --> 将转换后的数字\n添加到结果列表中 判断字符是否\n为大写字母 -- 除A以外的\n25个大写字母 --> 根据题设转换规则\n转换为相应的小写字母 --> 从字典中查找小写字母\n并转换为对应的数字 --> 将转换后的数字\n添加到结果列表中 -
将结果转换为字符串并返回
使用
''.join(result)将列表result中的字符连接成一个字符串。return ''.join(result)
完整代码
def solution(s: str) -> str:
# 小写字母到数字的映射
letter_to_digit = {
'a': '2', 'b': '2', 'c': '2',
'd': '3', 'e': '3', 'f': '3',
'g': '4', 'h': '4', 'i': '4',
'j': '5', 'k': '5', 'l': '5',
'm': '6', 'n': '6', 'o': '6',
'p': '7', 'q': '7', 'r': '7', 's': '7',
't': '8', 'u': '8', 'v': '8',
'w': '9', 'x': '9', 'y': '9', 'z': '9'
}
result = []
for char in s:
if char.islower():
result.append(letter_to_digit[char])
elif char.isupper():
if char == 'A':
result.append('9')
else:
lower_char = chr(ord(char.lower()) - 1)
result.append(letter_to_digit[lower_char])
else:
result.append(char)
return ''.join(result)
if __name__ == '__main__':
print(solution(s="LIming0701") == '5464640701')
print(solution(s="PassW0rd") == '62778073')
print(solution(s="helloWORLD123") == '4355686752123')