1044 火星数字 (20 分)
题意描述:
火星人是以 13 进制计数的:
- 地球人的 0 被火星人称为 tret。
- 地球人数字 1 到 12 的火星文分别为:jan, feb, mar, apr, may, jun, jly, aug, sep, oct, nov, dec。
- 火星人将进位以后的 12 个高位数字分别称为:tam, hel, maa, huh, tou, kes, hei, elo, syy, lok, mer, jou。
例如地球人的数字 29 翻译成火星文就是 hel mar;而火星文 elo nov 对应地球数字 115。
为了方便交流,请你编写程序实现地球和火星数字之间的互译。
输入格式:
输入第一行给出一个正整数 N(<100),随后 N 行,每行给出一个 [0, 169) 区间内的数字 —— 或者是地球文,或者是火星文。
输出格式:
对应输入的每一行,在一行中输出翻译后的另一种语言的数字。
输入样例:
4
29
5
elo nov
tam
输出样例:
hel mar
may
115
13
解题思路:
Alice: 你感觉怎么样 ?
Bob: 太棒了 !
Alice: 什么太棒 了!,╭(╯^╰)╮
, 我是问你这道题目怎么样,你想啥呢 !
Bob: 啊, 这道题啊,没啥的。逻辑上复杂一点,不过没有什么难度。
Alice: (゚Д゚#)
哪里复杂了,挺简单的啊。你看,不就是先 判断输入的是火星文数字还是地球数字,如果是地球数字就变成火星文数字,如果是火星文数字就变成地球数字,然后输出嘛。
Bob:恩,不错不错,main( )
函数就应该这么写。
Alice: 然后具体的话, 地球数字转换为火星文,如果是0
就直接返回‘tret
’,不是零的就先求出这个地球数字的13进制
的十位和个位。然后
Bob: 等等,ヽ(゚Д゚)ノ
怎么13进制的十位和个位??13进制也能叫做十位和个位???
Alice: 就这样称呼嘛,就是倒数第二位和第一位啊。你看题目给的范围,[0 169)转换成13进制的时候最多也就两位数字了。然后就按照题目中给的映射,把13进制数字换成火星文就好了。
Bob: 还有什么要补充的吗 ?
Alice:有啊,地球数字变成火星文的时候没有“前导零”, 也没有“后缀零”。火星文变成地球数字的时候,有可能只有一位火星数字,这时候需要进一步判断这一位火星数字对应的是十位还是个位。
Bob: 可以啊,这逻辑,简直滴水不漏 啊。
Alice: 那是,ヾ(๑╹◡╹)ノ"
Bob: ヽ(゚∀゚)メ(゚∀゚)ノ
代码:
def main():
N = int(input())
# 接收 整数 N
for x in range(N):
temp = input()
# 每次读入一个数字
if is_number(temp[0]):
# 如果这个数字是地球数字,就把它变成火星数字然后输出
print(earth2mars(temp))
else:
# 如果这个数字是火星数字,就把它变成地球数字然后输出
print(mars2earth(temp))
def earth2mars(temp):
# 把地球数字变成火星数字,输入是地球数字的字符串表示,输出是火星数字的字符串表示。
number = int(temp)
if number == 0:
return 'tret'
# 如果输入的数字是0, 对应火星文中的 tret
else:
# 如果非零,与[1, 168]之间的地球数字对应的火星文中不再有‘tret’出现。
ones = number % 13
tens = number // 13
# 由于输入地球数字的范围是[1, 168],也就是说最多对应两位的火星文。所以先分别求出两位火星文对应的数字。
# 因为火星文数字直接对应的是地球上的13进制,所以先得到地球数字的13进制表示。
# ones表示13进制的个位数,tens表示13进制的十位数。
ones_dict = dict(zip([x for x in range(1, 13)], [
'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jly', 'aug', 'sep', 'oct', 'nov', 'dec']))
tens_dict = dict(zip([x for x in range(1, 13)], [
'tam', 'hel', 'maa', 'huh', 'tou', 'kes', 'hei', 'elo', 'syy', 'lok', 'mer', 'jou']))
# 用字典建立起地球13进制数 到 火星文数字的映射,由于火星文的奇葩规定,个位上的数字和十位上的数字分别建立了两个映射。
if tens in tens_dict:
# 如果能成功映射(tens == 0 时 不能成功映射),就把地球数字13进制的十位数转换为火星文数字
tens = tens_dict[tens]
else:
tens = ''
# 根据题意,tens == 0时,要对应 '' 而不是 'tret'。
if ones in ones_dict:
ones = ones_dict[ones]
else:
ones = ''
return "{} {}".format(tens, ones).strip()
# 将tens和ones填入字符串,由于tens和ones可能是空字符串,这样就会在答案字符串的首部或者尾部有多余的空格出现。
# 所以我们需要strip()来去除多余的空格。
def mars2earth(temp):
# 把火星数字变成地球数字,输入是火星数字的字符串表示,输出是地球数字。
if temp == 'tret':
return 0
# 如果输入是'tret'就是地球数字的零啦。
else:
ones_dict = dict(zip(['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jly',
'aug', 'sep', 'oct', 'nov', 'dec'], [x for x in range(1, 13)]))
tens_dict = dict(zip(['tam', 'hel', 'maa', 'huh', 'tou', 'kes', 'hei',
'elo', 'syy', 'lok', 'mer', 'jou'], [x for x in range(1, 13)]))
# 建立起火星文数字到地球数字的映射,注意这里的映射和上面函数中映射刚好是相反的。
temp = temp.split(" ")
# 只能是temp.split(" "),如果写成temp.split()就会把只有一个数位的火星文拆开,如tam -> 't','a','m'
if len(temp) == 2:
#如果有两位数字的话, 分别将其映射会地球数字的十位和个位
tens = tens_dict[temp[0]]
ones = ones_dict[temp[1]]
elif len(temp) == 1:
# 如果只有一位数字,那它既可能是个位数也可能是十位数。
if temp[0] in tens_dict:
# 如果这个数字是十位数,映射为十位数,而且此时个位数是0。
tens = tens_dict[temp[0]]
ones = 0
else:
# 如果这个数字是个位数,映射为个位数,而且此时十位数是0。
tens = 0
ones = ones_dict[temp[0]]
return tens * 13 + ones
# 把得到的13进制数的十位和个位组合成10进制整数。
def is_number(char):
"""判断一个字符是否是数字字符"""
return char in "0123456789"
if __name__ == '__main__':
main()
易错点:
- 火星文数字是13进制的,所以在和地球数字的互换中要先变成13进制的,才好建立起映射。
- 火星文数字中只有个位上的零,没有前导零,也没有十位上一个数字个位上跟着一个零的情况。这都是因为火星文中个位数字用了一套字符,十位数字用了另一套字符。
总结:
-
判断一个字符是否是数字字符至少有两种写法:
return char in '0123465798' # method 1 return ord(char) <= ord('9') and ord(char) >= ord('0') method 2
-
10 进制转换为其他进制 的方法有: 除K取余法
-
用字典将一个列表和其下标建立起映射关系:
maps = dict(zip(range(len(object_list)), object_list))
其实质是使用zip函数( ) 和两个列表生成字典。