小M的37进制数字相乘问题 | 豆包MarsCode AI刷题

74 阅读3分钟

小M的37进制数字相乘问题

问题描述

小M最近在学习37进制的表示方法。37进制使用的字符集是:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$",其中字符依次代表从0到36的数字。现在,给定两个37进制的数字aa和bb,请你计算它们的乘积并输出结果,结果也需使用37进制表示。

解题思路

  1. 字符到数字的转换:将37进制的字符转换为对应的整数值。

  2. 数字到字符的转换:在计算结果后,将整数值转换回37进制的字符。

  3. 乘法实现:将两个37进制的字符串转换为整数,进行乘法运算,然后将结果转换回37进制的字符串。

  4. 处理进位:处理10进制和37进制字符串之间的进位问题。

代码实现

字符到数字的转换

将37进制的字符转换为对应的整数值。可以使用字典来实现这个映射,具体代码如下:

char_to_int = {
    '0': 0, '1': 1, '2': 2, '3': 3, '4': 4,
    '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
    'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15, 'G': 16,
    'H': 17, 'I': 18, 'J': 19, 'K': 20, 'L': 21, 'M': 22, 'N': 23,
    'O': 24, 'P': 25, 'Q': 26, 'R': 27, 'S': 28, 'T': 29, 'U': 30,
    'V': 31, 'W': 32, 'X': 33, 'Y': 34, 'Z': 35, '$': 36
}

或者将上述代码简化为以下代码:

char_to_int = {char: idx for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$")}

简化后的代码使用了enumerate()函数辅助构建字典。该函数用于将一个可遍历的数据对象(如列表、元组或字符串,在此步骤中指37进制使用的字符组成的字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在for循环当中。

上述代码还使用了for循环的简写操作,实际上等价于以下代码:

char_to_int = {}
for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$"):
    char_to_int[char] = idx

数字到字符的转换

在计算结果后,将整数值转换回37进制的字符。同样可以使用字典来实现这个映射。具体代码如下:

int_to_char = {
    0: '0', 1: '1', 2: '2', 3: '3', 4: '4',
    5: '5', 6: '6', 7: '7', 8: '8', 9: '9',
    10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F', 16: 'G',
    17: 'H', 18: 'I', 19: 'J', 20: 'K', 21: 'L', 22: 'M', 23: 'N',
    24: 'O', 25: 'P', 26: 'Q', 27: 'R', 28: 'S', 29: 'T', 30: 'U',
    31: 'V', 32: 'W', 33: 'X', 34: 'Y', 35: 'Z', 36: '$'
}

或者将上述代码简化为以下代码:

int_to_char = {idx: char for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$")}

乘法实现

将两个37进制的字符串转换为整数,进行乘法运算,然后将结果转换回37进制的字符串。这里需要用到两个用于处理进位的自定义函数,分别命名为to_intto_base37,这两个函数的具体内容稍后介绍。

int_a = to_int(a)
int_b = to_int(b)
product = int_a * int_b

return to_base37(product)

处理进位

在将结果转换回37进制字符串时,需要注意处理进位问题。这里需要定义上一步骤提到的两个自定义函数to_intto_base37

进制最基本的原理就是逢X进一位。以solution("ZZ", "X")为例,该测试用例实际上的运算过程如下:

ZZ(37) = 35 × 371 + 35 × 370 = 1330

X(37) = 33 × 370 = 33

1330 × 33 = 43890 = 32 × 372 + 2 × 371 + 8 × 370 = W28(37)

该步骤实际的思路,就是将这样的运算过程用编程语言表示。

  1. 37进制转10进制to_int函数)

    def to_int(s: str) -> int:
        num = 0
        for char in s:
            num = num * 37 + char_to_int[char]
        return num
    

    该函数的实际原理是按权求和,即将37进制数按位权形式展开多项式和的形式,求其最后的和,就是其对应的十进制数。以37进制数字ZZ为例,该数字各数位的数字和位权如下表:

    名称
    数位3535
    位权371370

    因此,to_int('ZZ')的实际运算方式如下:

    ZZ(37) = 35 × 371 + 35 × 370 = 1330

  2. 10进制转37进制to_base37函数)

    def to_base37(num: int) -> str:
        if num == 0:
            return "0"
        result = []
        while num > 0:
            result.append(int_to_char[num % 37])
            num //= 37
        return ''.join(result[::-1]) #使用result[::-1]将取得的余数逆序排列
    

    该函数的实际原理是除X取余法,在此步骤中指用37连续除十进制数,直到商为0,逆序排列余数得到结果。以to_base37(43890)为例,该函数的原理可以用下图表示:

    43890转W28.png

    将取得的余数逆序排列,得到一个37进制的3位数,百位、十位和个位分别是3228。由于最右侧的32在字符集中所对应的字母是W,因此to_base37(43890)实际返回的结果是'W28'

完整代码

def solution(a: str, b: str) -> str:
    # write code here
    char_to_int = {char: idx for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$")}
    int_to_char = {idx: char for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$")}
    
    def to_int(s: str) -> int:
        num = 0
        for char in s:
            num = num * 37 + char_to_int[char]
        return num
    
    def to_base37(num: int) -> str:
        if num == 0:
            return "0"
        result = []
        while num > 0:
            result.append(int_to_char[num % 37])
            num //= 37
        return ''.join(result[::-1])
    
    int_a = to_int(a)
    int_b = to_int(b)
    product = int_a * int_b
    
    return to_base37(product)

if __name__ == '__main__':
    print(solution("ZZ", "X") == 'V8') #实际输出结果为False
    print(solution("A", "B") == '2$') #实际输出结果为True