在一本书里看到一段罗马数字的程序, 需求如下,自己试着用python和erlang各写了一遍,感觉有些地方还是不太舒服,大家看看这个程序还能怎么改改更好
你可能经常看到罗马数字,即使你没有意识到它们。你可能曾经在老电影或者电视中看到它们 (“版权所有
MCMXLVI” 而不是 “版权所有1946”),或者在某图书馆或某大学的贡献墙上看到它们 (“成立于
MDCCCLXXXVIII”而不是“成立于1888”)。你也可能在某些文献的大纲或者目录上看到它们。这是一个表示数字的系统,它实际上能够追溯到远古的罗马帝国 (因此而得名)。
在罗马数字中,利用7个不同字母进行重复或者组合来表达各式各样的数字。
I=1V=5X=10L=50C=100D=500M=1000
下面是关于构造罗马数字的一些通用的规则的介绍:
- 字符是叠加的。
I表示1,II表示2,而III表示3。VI表示6(字面上为逐字符相加,“5加1”),VII表示7,VIII表示8。 - 含十字符 (
I、X、C和M) 至多可以重复三次。对于4,你则需要利用下一个最大的含五字符进行减操作得到:你不能把4表示成IIII,而应表示为IV(“比5小1”)。数字40写成XL(比50小10),41写成XLI,42写成XLII,43写成XLIII,而44写成XLIV(比50小10,然后比5小1)。 - 类似地,对于数字
9,你必须利用下一个含十字符进行减操作得到:8表示为VIII,而9则表示为IX(比10小1),而不是VIIII(因为字符I不能连续重复四次)。数字90表示为XC,900表示为CM。 - 含五字符不能重复。数字
10常表示为X,而从来不用VV来表示。数字100常表示为C,也从来不表示为LL。 - 罗马数字一般从高位到低位书写,从左到右阅读,因此不同顺序的字符意义大不相同。
DC表示600;而CD是一个完全不同的数字 (为400,也就是比500小100)。CI表示101;而IC甚至不是一个合法的罗马字母 (因为你不能直接从数字100减去1;这需要写成XCIX,意思是比100小10,然后加上数字9,也就是比10小1的数字)。
python版本:
ADD, DEL, UNIT, DECADE, HUNDRED, THOUSEND = 0, 1, 1, 10, 100, 1000
Compute = lambda a,x,y: x + y if a == ADD else y + x
def mapRoman(Num):
mapFun = mapNum()
return reduce(lambda x,y: x + y, map(mapFun,subtractNum(Num, THOUSEND, [])))
def subtractNum(Num, Level, Result):
if Num == 0 :
return Result if Level == 0 else subtractNum(0, Level/10, Result + [(0, Level)])
NewNum = Num / Level
ModNum = Num % Level
return subtractNum(ModNum, Level/10, Result + [(NewNum, Level)])
def mapNum():
def func((Num, Level)):
Action,ActionNum,Src,Dst = getAction(Num, Level)
return getActionResult(Action,ActionNum,Src,Dst)
return func
def getAction(Num, Level):
Dict = {UNIT:("I","V","X"), DECADE:("X", "L", "C"), HUNDRED:("C", "D", "M"), THOUSEND:("M", "", "")}
One, Five, Ten = Dict[Level]
if Num in range(1, 4):
return ADD, Num - 1, One, One
elif Num in range(5, 9):
return ADD, Num - 5, Five, One
elif Num == 4:
return DEL, 1, Five, One
elif Num == 9:
return DEL, 1, Ten, One
else:
return ADD, 0, "", ""
def getActionResult(Action,Num,Src,Dst):
if Num == 0: return Src
return getActionResult(Action, Num - 1, Compute(Action, Src, Dst), Dst)
测试 myassert("MDCCCLXXXVIII", mapRoman(1888))
罗马数字转换器
14

被折叠的 条评论
为什么被折叠?



