# Merchant’s Guide To The Galaxy笔试题解析 python解决 罗马数字转阿拉伯数字

### １．说明

1.题目应在本周5中午十二点之前提交

2.题目测试考察包含对题意的理解以及代码整洁度和简易度,测试的数据会变动

3.最好有相关的单元测试,如果能达到100%测试覆盖率且能正确的使用mock对象最好.如果时间不够或者不熟悉测试方法否,这一部分可忽略.功能完整性是首要考察.

4.建议使用github或其它git托管工具托管一份,提交时直接给出链接.合理的commit,如果符合小步更改提交的准则会有加分.

### ２．Merchant’s Guide To The Galaxy

Python

Description You decided to give up on earth after the latest financial collapse left 99.99% of the earth's population with 0.01% of the wealth. Luckily, with the scant sum of money that is left in your account, you are able to afford to rent a spaceship, leave earth, and fly all over the galaxy to sell common metals and dirt (which apparently is worth a lot). Buying and selling over the galaxy requires you to convert numbers and units, and you decided to write a program to help you. The numbers used for intergalactic transactions follows similar convention to the roman numerals and you have painstakingly collected the appropriate translation between them. Numbers are formed by combining symbols together and adding the values. For example, MMVI is 1000 + 1000 + 5 + 1 = 2006. Generally, symbols are placed in order of value, starting with the largest values. When smaller values precede larger values, the smaller values are subtracted from the larger values, and the result is added to the total. For example MCMXLIV = 1000 + (1000 − 100) + (50 − 10) + (5 − 1) = 1944. The symbols "I", "X", "C", and "M" can be repeated three times in succession, but no more. (They may appear four times if the third and fourth are separated by a smaller value, such as XXXIX.) "D", "L", and "V" can never be repeated. "I" can be subtracted from "V" and "X" only. "X" can be subtracted from "L" and "C" only. "C" can be subtracted from "D" and "M" only. "V", "L", and "D" can never be subtracted. Only one small-value symbol may be subtracted from any large-value symbol. A number written in Arabic numerals can be broken into digits. For example, 1903 is composed of 1, 9, 0, and 3. To write the Roman numeral, each of the non-zero digits should be treated separately. In the above example, 1,000 = M, 900 = CM, and 3 = III. Therefore, 1903 = MCMIII. Input to your program consists of lines of text detailing your notes on the conversion between intergalactic units and roman numerals. You are expected to handle invalid queries appropriately. INPUT: glob is I prok is V pish is X tegj is L glob glob Silver is 34 Credits glob prok Gold is 57800 Credits pish pish Iron is 3910 Credits how much is pish tegj glob glob ? how many Credits is glob prok Silver ? how many Credits is glob prok Gold ? how many Credits is glob prok Iron ? OUTPUT pish tegj glob glob is 42 glob prok Silver is 68 Credits glob prok Gold is 57800 Credits glob prok Iron is 782 Credits

1234567891011121314151617181920212223242526272829303132

Description You decided to give up on earth after the latest financial collapse left 99.99% of the earth's population with 0.01% of the wealth. Luckily, with the scant sum of money that is left in your account, you are able to afford to rent a spaceship, leave earth, and fly all over the galaxy to sell common metals and dirt (which apparently is worth a lot). Buying and selling over the galaxy requires you to convert numbers and units, and you decided to write a program to help you. The numbers used for intergalactic transactions follows similar convention to the roman numerals and you have painstakingly collected the appropriate translation between them. Numbers are formed by combining symbols together and adding the values. For example, MMVI is 1000 + 1000 + 5 + 1 = 2006. Generally, symbols are placed in order of value, starting with the largest values. When smaller values precede larger values, the smaller values are subtracted from the larger values, and the result is added to the total. For example MCMXLIV = 1000 + (1000 − 100) + (50 − 10) + (5 − 1) = 1944. The symbols "I", "X", "C", and "M" can be repeated three times in succession, but no more. (They may appear four times if the third and fourth are separated by a smaller value, such as XXXIX.) "D", "L", and "V" can never be repeated. "I" can be subtracted from "V" and "X" only. "X" can be subtracted from "L" and "C" only. "C" can be subtracted from "D" and "M" only. "V", "L", and "D" can never be subtracted. Only one small-value symbol may be subtracted from any large-value symbol. A number written in Arabic numerals can be broken into digits. For example, 1903 is composed of 1, 9, 0, and 3. To write the Roman numeral, each of the non-zero digits should be treated separately. In the above example, 1,000 = M, 900 = CM, and 3 = III. Therefore, 1903 = MCMIII. Input to your program consists of lines of text detailing your notes on the conversion between intergalactic units and roman numerals. You are expected to handle invalid queries appropriately. INPUT:glob is Iprok is Vpish is Xtegj is Lglob glob Silver is 34 Creditsglob prok Gold is 57800 Creditspish pish Iron is 3910 Creditshow much is pish tegj glob glob ?how many Credits is glob prok Silver ?how many Credits is glob prok Gold ?how many Credits is glob prok Iron ? OUTPUTpish tegj glob glob is 42glob prok Silver is 68 Creditsglob prok Gold is 57800 Creditsglob prok Iron is 782 Credits

### ３．题意解析

#### 3.1 　题目说明

0.如果小数字的出现在大数字的前面则表示减．例如MCMXLIV = 1000 + (1000 − 100) + (50 − 10) + (5 − 1) = 1944.

1. I：可以表示十进制数字1，V：可以表示十进制数字5，X：可以表示十进制数字10，L：可以表示十进制数字50，C：可以表示十进制数字100，D：可以表示十进制数字500，M：可以表示十进制数字1000；

2.I, X, C, and M可以重复出现最多3次；（这个不好处理一点）

3.一般是从后往前排列：即MDCLXVI的顺序，当然也允许相邻的两个倒序，但是需要符合以下规则:

I ：只能组合IV ,IX

X：只能组合XL，XC

C：只能组合CD，CM

V，L，D不能倒序

#### ３．２　测试数据解析

Python

glob is I prok is V pish is X tegj is L glob glob Silver is 34 Credits glob prok Gold is 57800 Credits pish pish Iron is 3910 Credits how much is pish tegj glob glob ? how many Credits is glob prok Silver ? how many Credits is glob prok Gold ? how many Credits is glob prok Iron ?

1234567891011

glob is Iprok is Vpish is Xtegj is Lglob glob Silver is 34 Creditsglob prok Gold is 57800 Creditspish pish Iron is 3910 Creditshow much is pish tegj glob glob ?how many Credits is glob prok Silver ?how many Credits is glob prok Gold ?how many Credits is glob prok Iron ?

Python

OUTPUT pish tegj glob glob is 42 glob prok Silver is 68 Credits glob prok Gold is 57800 Credits glob prok Iron is 782 Credits

12345

OUTPUTpish tegj glob glob is 42glob prok Silver is 68 Creditsglob prok Gold is 57800 Creditsglob prok Iron is 782 Credits

Python

glob glob Silver is 34 Credits ＃说明ＩＩ（２）个银币是34元（基础货币单位）则可以得出一个银币是17元

12

glob glob Silver is 34 Credits＃说明ＩＩ（２）个银币是34元（基础货币单位）则可以得出一个银币是17元

Python

how many Credits is glob prok Silver ? ＃问．ＩＶ（４）个银币是多少元，可以得出34/2*4＝68，符合输出结果

12

how many Credits is glob prok Silver ?＃问．ＩＶ（４）个银币是多少元，可以得出34/2*4＝68，符合输出结果

### 4.1 Roma 数字转阿拉伯数字

Python

#coding:utf-8 import re #正则表达式 def getRomanNum(RomanStr): ''' 输入罗马数字字符串，输出转换后的阿拉伯字符串 逻辑说明:原本是使用所有规则一个个if来判断处理的,但是这样的代码非常垃圾,学习后改进. 使用正则的类似思想,对输入串判断romanpattern中规则出现的情况, 例如以MXCVI为例,则在pattern的结果是:^M{1}C{0}XCX{0}VI{1} 1000+90+6这里就可以按照千百十分位来分别判断处理 其中retnum则是存放转化后的阿拉伯数字,用于返回. ''' #正则表达式进行匹配,判断输入是否合法 if re.search('^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\$',RomanStr)!=None: NumDic = {"pattern":"","retNum":0}#值记录区 # 如测试数为 XCVI 则最后retNum 96 pattern ^M{0}C{0}XCX{0}VI{1} 展示出现数次 RomanPattern = { "0":('','','','M'), # 1000 "1":('CM','CD','D','C',100), #900 400 500 100 "2":('XC','XL','L','X',10), #90 40 50 10 "3":('IX','IV','V','I',1)#9 4 5 1 } i = 3 NumItems = sorted(RomanPattern.items())#对字典先排序返回元组 for RomanItem in NumItems: if RomanItem[0] != '0':#先统计千内的 patstr = NumDic["pattern"].join(['',RomanItem[1][0]]) #print "R "+RomanItem[1][0] if re.search(patstr,RomanStr) != None:#先判断Romanstr中是否存在parstr NumDic["retNum"] += 9*RomanItem[1][4] # +=90 NumDic["pattern"] = patstr #存放正则信息 else: patstr = NumDic["pattern"].join(['',RomanItem[1][1]]) #print patstr if re.search(patstr,RomanStr) != None: NumDic["retNum"] += 4*RomanItem[1][4] #+=40 NumDic["pattern"] = patstr else: patstr = NumDic["pattern"].join(['',RomanItem[1][2]]) if re.search(patstr,RomanStr) != None: NumDic["retNum"] += 5*RomanItem[1][4] # += 50 NumDic["pattern"] = patstr # test #print "retNum " + str(NumDic["retNum"]) , #print "pattern " +NumDic["pattern"] if NumDic["pattern"] == '': NumDic["pattern"] = '^'#标志 tempstr = '' sum = 0 for k in range(0,4):#处理连续出现几次 pstr = RomanItem[1][3].join(['','{']).join(['',str(k)]).join(['','}']) patstr = NumDic["pattern"].join(['',pstr]) if re.search(patstr,RomanStr) != None: sum = k*(10**i) tempstr = patstr if tempstr <> '':#不等于即依旧为原始值 NumDic["pattern"] = tempstr else: NumDic["pattern"] = patstr NumDic['retNum'] += sum i -= 1 return NumDic['retNum'] #return NumDic['pattern'] else: print 'String is not a valid Roman numerals' print getRomanNum('MXCVI')

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869

#coding:utf-8import re #正则表达式 def getRomanNum(RomanStr):    '''    输入罗马数字字符串，输出转换后的阿拉伯字符串    逻辑说明:原本是使用所有规则一个个if来判断处理的,但是这样的代码非常垃圾,学习后改进.    使用正则的类似思想,对输入串判断romanpattern中规则出现的情况,    例如以MXCVI为例,则在pattern的结果是:^M{1}C{0}XCX{0}VI{1} 1000+90+6这里就可以按照千百十分位来分别判断处理    其中retnum则是存放转化后的阿拉伯数字,用于返回.    '''    #正则表达式进行匹配,判断输入是否合法    if re.search('^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\$',RomanStr)!=None:        NumDic = {"pattern":"","retNum":0}#值记录区        # 如测试数为 XCVI 则最后retNum 96 pattern ^M{0}C{0}XCX{0}VI{1} 展示出现数次        RomanPattern = {            "0":('','','','M'),             #          1000            "1":('CM','CD','D','C',100), #900 400 500 100            "2":('XC','XL','L','X',10), #90 40 50 10            "3":('IX','IV','V','I',1)#9 4 5 1            }        i = 3        NumItems = sorted(RomanPattern.items())#对字典先排序返回元组         for RomanItem in NumItems:            if RomanItem[0] != '0':#先统计千内的                patstr = NumDic["pattern"].join(['',RomanItem[1][0]])                #print "R "+RomanItem[1][0]                if re.search(patstr,RomanStr) != None:#先判断Romanstr中是否存在parstr                    NumDic["retNum"] += 9*RomanItem[1][4] # +=90                    NumDic["pattern"] = patstr #存放正则信息                else:                    patstr = NumDic["pattern"].join(['',RomanItem[1][1]])                    #print patstr                    if re.search(patstr,RomanStr) != None:                        NumDic["retNum"] += 4*RomanItem[1][4] #+=40                        NumDic["pattern"] = patstr                    else:                        patstr = NumDic["pattern"].join(['',RomanItem[1][2]])                        if re.search(patstr,RomanStr) != None:                            NumDic["retNum"] += 5*RomanItem[1][4] # += 50                            NumDic["pattern"] = patstr            # test            #print "retNum " + str(NumDic["retNum"]) ,            #print "pattern " +NumDic["pattern"]             if NumDic["pattern"] == '':                NumDic["pattern"] = '^'#标志            tempstr = ''            sum = 0            for k in range(0,4):#处理连续出现几次                pstr = RomanItem[1][3].join(['','{']).join(['',str(k)]).join(['','}'])                patstr = NumDic["pattern"].join(['',pstr])                if re.search(patstr,RomanStr) != None:                    sum = k*(10**i)                    tempstr = patstr            if tempstr <> '':#不等于即依旧为原始值                NumDic["pattern"] = tempstr            else:                NumDic["pattern"] = patstr            NumDic['retNum'] += sum            i -= 1         return NumDic['retNum']        #return NumDic['pattern']    else:        print 'String is not a valid Roman numerals' print getRomanNum('MXCVI')

### 4.2 输入的字符串解析

Python

#coding:utf-8 from Roma_to_num_test import getRomanNum Romanarray=['I','V','X','L','C','D','M'] word_dic = {}#以字典来对应单词和罗马数字 coin_dic = {}#以字典来对应货币和价值 def str_Resolve(input_line): ''' 输入每一行的字符串类型信息:如题目中的测试数据.返回分类机处理后的信息. 程序代码说明: 结构很明显,按照末尾字符是否在Romanarray中,判断是否是第一类定义单词输入 否则判断是否以小写s结束,判断是否是作为第二类金币银币类型输入 否则判断末尾是否是?号为第三类输入.进行按照空格划分之后判断第二个单词 按照many和mach进行分别返回处理 ''' if input_line[-1] in Romanarray: input_line_array = input_line.split(' ')#以空格截取 word_dic[input_line_array[0]] = input_line_array[2]#取第一个和最后一个元素 return #print 'word_dic:',word_dic: elif input_line[-1] == 's':#以小写ｓ做为金币银币那些测试数据的识别符号 input_line_array = input_line.split(' ')#以空格截取 temp_str = '' for i in range(len(input_line_array)-4): temp_str += word_dic[input_line_array[i]] temp_num = getRomanNum(temp_str) #print "input_line_array[-4]",input_line_array[-4] coin_dic[input_line_array[-4]] = int(input_line_array[-2])/int(temp_num) return #print 'coin_dic:',coin_dic elif input_line[-1] == '?': #以?为标志,判断是否是第三四类输入 input_line_array = input_line.split(' ') #print "input_line_array:",input_line_array if input_line_array[1] == 'much': temp_str1 = '' temp_str3 = '' for i in range(3,len(input_line_array)-1):#抽取第四个到最后一个数组元素 temp_str3 += input_line_array[i]+' ' temp_str1 += word_dic[input_line_array[i]] return temp_str3+"is "+str(getRomanNum(temp_str1))#转化成数字并且输出 elif input_line_array[1] == 'many':#处理ｍａｎｙ temp_str2 = '' temp_str4 = '' for i in range(4,len(input_line_array)-2):#取第５个到倒数第三个之间 temp_str4 += input_line_array[i]+' ' temp_str2 += word_dic[input_line_array[i]]#转化为字符进行ｒｏｍａ查询 return temp_str4+input_line_array[-2]+' is '+ str(coin_dic[input_line_array[-2]]*getRomanNum(temp_str2) )+ ' Credits'#输出数量＊单位价值

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859

#coding:utf-8from Roma_to_num_test import getRomanNum Romanarray=['I','V','X','L','C','D','M'] word_dic = {}#以字典来对应单词和罗马数字coin_dic = {}#以字典来对应货币和价值 def str_Resolve(input_line):    '''    输入每一行的字符串类型信息:如题目中的测试数据.返回分类机处理后的信息.     程序代码说明:    结构很明显,按照末尾字符是否在Romanarray中,判断是否是第一类定义单词输入    否则判断是否以小写s结束,判断是否是作为第二类金币银币类型输入    否则判断末尾是否是?号为第三类输入.进行按照空格划分之后判断第二个单词    按照many和mach进行分别返回处理    '''    if input_line[-1] in Romanarray:        input_line_array = input_line.split(' ')#以空格截取        word_dic[input_line_array[0]] = input_line_array[2]#取第一个和最后一个元素        return    #print 'word_dic:',word_dic:     elif input_line[-1] == 's':#以小写ｓ做为金币银币那些测试数据的识别符号        input_line_array = input_line.split(' ')#以空格截取         temp_str = ''        for i in range(len(input_line_array)-4):            temp_str += word_dic[input_line_array[i]]         temp_num =  getRomanNum(temp_str)        #print "input_line_array[-4]",input_line_array[-4]        coin_dic[input_line_array[-4]] = int(input_line_array[-2])/int(temp_num)        return    #print 'coin_dic:',coin_dic     elif input_line[-1] == '?': #以?为标志,判断是否是第三四类输入        input_line_array = input_line.split(' ')        #print "input_line_array:",input_line_array         if input_line_array[1] == 'much':            temp_str1 = ''            temp_str3 = ''            for i in range(3,len(input_line_array)-1):#抽取第四个到最后一个数组元素                temp_str3 += input_line_array[i]+' '                temp_str1 += word_dic[input_line_array[i]]             return temp_str3+"is "+str(getRomanNum(temp_str1))#转化成数字并且输出          elif input_line_array[1] == 'many':#处理ｍａｎｙ            temp_str2 = ''            temp_str4 = ''            for i in range(4,len(input_line_array)-2):#取第５个到倒数第三个之间                temp_str4 += input_line_array[i]+' '                temp_str2 += word_dic[input_line_array[i]]#转化为字符进行ｒｏｍａ查询             return temp_str4+input_line_array[-2]+' is '+ str(coin_dic[input_line_array[-2]]*getRomanNum(temp_str2) )+ ' Credits'#输出数量＊单位价值

### 4.3 使用文件读取测试数据的main.py

Python

#coding:utf-8 from str_Resolve import * import fileinput ''' 测试/使用说明: 请将新的测试数据,使用文本的形式存放在test-data文件夹下,同时修改文件读取的路径 ''' for line in fileinput.input("../test-data/input_2.txt"): str_line=line[:-1]#去除行结尾的换行符号,未知为何会多出一个换行 ,根据环境不同可能有差别 #print str_line try: str_return = str_Resolve(str_line) if str_return: print str_return except: print "I have no idea what you are talking about"

1234567891011121314151617

#coding:utf-8from str_Resolve import *import fileinput'''测试/使用说明:请将新的测试数据,使用文本的形式存放在test-data文件夹下,同时修改文件读取的路径''' for line in fileinput.input("../test-data/input_2.txt"):    str_line=line[:-1]#去除行结尾的换行符号,未知为何会多出一个换行 ,根据环境不同可能有差别    #print str_line    try:        str_return = str_Resolve(str_line)        if str_return:            print str_return    except:        print "I have no idea what you are talking about"

0 条评论

• ### 背包九讲－问法的灵活变化

要求的是“总价值最小”“总件数最小”，只需简单的将上面的状态转移方程中的max改成min即可。

• ### C的|、||、&、&&、异或、~、！运算 位运算

研究这个的起因是我遇到一个题目，判断一个数是奇偶数，这个很简单，但是又个最佳代码 判断奇偶时用了

• ### python常用函数总结

类型转换函数，操作系统相关的调用，系统相关的信息模块 ，操作系统相关的调用和操作 import os，操作举例，用os.path编写平台无关的程序，文件操作，r...

• ### 关于C++中Hash的应用

本文只介绍我们在C++中如何使用Hash这种数据结构达到我们编程的目的，有关Hash的概念和实现不做详谈。

java.base/java/util/concurrent/Executor.java

• ### python之OS模块（对文件or目录操

os，语义为操作系统，包含普遍的操作系统功能，与具体的平台无关。python编程时，处理文件和目录这些操作，就比如说：显示当前目录下所有文件/删除某个文件/...

• ### 一日一工具|Python实现5行代码生成短链

pyshorteners提供了18种短链根域名供使用，作者提供了口子，如果你有发现比较好用在线短链服务的也可以贡献代码。

• ### systemtap实现定位内核丢包工具

前些日子业务报过来一个容器作为http client访问http server出现随机性丢包超时问题，经过抓包分析确定在虚拟机端口eth0到Pod所在的veth...