小T的密码变换规则 | 豆包MarsCode AI刷题

150 阅读5分钟

小T的密码变换规则

问题描述

小T设计了一套密码变换规则,将输入的字符串转换成一串数字密码。变换规则如下:

  1. 小写字母按以下映射关系进行转换:
  • a, b, c -> 2
  • d, e, f -> 3
  • g, h, i -> 4
  • j, k, l -> 5
  • m, n, o -> 6
  • p, q, r, s -> 7
  • t, u, v -> 8
  • w, x, y, z -> 9
  1. 大写字母先转为小写字母,再跳到字母表中的前一个字母,并按上述规则转换为对应的数字。例如,B 转换为 a,再转换为 2A 特殊处理,先变为 Z,再转换为 9
  2. 非字母字符保持不变。

例如:对于输入字符串 "LIming0701",转换后的数字密码为 5464640701

解题思路

  1. 遍历输入字符串的每个字符。
  2. 对于小写字母,直接从 letter_to_digit 字典中获取对应的数字。
  3. 对于大写字母,先转为小写字母,然后跳到字母表中的前一个字母,再从 letter_to_digit 字典中获取对应的数字。
  4. 对于非字母字符,直接添加到结果列表中。
  5. 最后,将结果列表中的元素连接成一个字符串并返回。

代码实现

  1. 初始化映射字典

    替换操作的初级方法就是使用if-elif-else语句。但是,写一大长串if-elif-else语句实在是太麻烦了,尤其是26个英文字母,大写+小写一共52个字符,如果用if-elif-else语句,不知道整段代码会写到什么时候。这种情况下,就需要先创建一个字典,再通过.get()函数取值。

    根据题目,小写字母的映射关系如下:

    • a, b, c -> 2
    • d, e, f -> 3
    • g, h, i -> 4
    • j, k, l -> 5
    • m, n, o -> 6
    • p, q, r, s -> 7
    • t, u, v -> 8
    • w, 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'
    }
    
  2. 遍历字符&判断字符

    首先,创建一个空列表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)
    
  3. 小写和大写字母的转换

    对于小写字母,根据题设变换规则,直接从 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添加到结果列表中
    
  4. 将结果转换为字符串并返回

    使用 ''.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')