我试图编写一个代码,将用户输入的整数转换为等效的罗马数字。到目前为止我所拥有的是:
generate_all_of_numeral
函数的要点是它为每个特定数字创建一个字符串。例如,generate_all_of_numeral(2400, 'M', 2000)
将返回字符串'MM'
。
我在主程序中挣扎。我开始找到M的罗马数字计数并将其保存到变量M.然后我减去M的次数乘以符号值,以便给出下一个值来处理下一个最大的数字。 / p>
向正确的方向点头?现在我的代码甚至不打印任何东西。
答案 0 :(得分:30)
处理此问题的最佳方法之一是使用divmod
函数。检查给定数字是否与从最高到最低的任何罗马数字匹配。在每场比赛中,你应该返回相应的角色。
使用模数函数时,某些数字会有余数,因此您也将相同的逻辑应用于余数。显然,我暗示递归。
请参阅下面的答案。我使用OrderedDict
来确保我可以向下“迭代”列表,然后使用divmod
的递归来生成匹配。最后,我join
生成了一个产生字符串的答案。
from collections import OrderedDict
def write_roman(num):
roman = OrderedDict()
roman[1000] = "M"
roman[900] = "CM"
roman[500] = "D"
roman[400] = "CD"
roman[100] = "C"
roman[90] = "XC"
roman[50] = "L"
roman[40] = "XL"
roman[10] = "X"
roman[9] = "IX"
roman[5] = "V"
roman[4] = "IV"
roman[1] = "I"
def roman_num(num):
for r in roman.keys():
x, y = divmod(num, r)
yield roman[r] * x
num -= (r * x)
if num <= 0:
break
return "".join([a for a in roman_num(num)])
抓住它:
num = 35
print write_roman(num)
# XXXV
num = 994
print write_roman(num)
# CMXCIV
num = 1995
print write_roman(num)
# MCMXCV
num = 2015
print write_roman(num)
# MMXV
答案 1 :(得分:20)
这是另一种方式,没有分裂:
num_map = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'),
(50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]
def num2roman(num):
roman = ''
while num > 0:
for i, r in num_map:
while num >= i:
roman += r
num -= i
return roman
# test
>>> num2roman(2242)
'MMCCXLII'
答案 2 :(得分:11)
曼哈顿算法的KISS版本,没有任何&#34;高级&#34;诸如OrderedDict
,递归,生成器,内部函数和break
之类的概念:
ROMAN = [
(1000, "M"),
( 900, "CM"),
( 500, "D"),
( 400, "CD"),
( 100, "C"),
( 90, "XC"),
( 50, "L"),
( 40, "XL"),
( 10, "X"),
( 9, "IX"),
( 5, "V"),
( 4, "IV"),
( 1, "I"),
]
def int_to_roman(number):
result = ""
for (arabic, roman) in ROMAN:
(factor, number) = divmod(number, arabic)
result += roman * factor
return result
一旦number
达到零,就可以添加一个prematurate退出,并且字符串累积可以更加pythonic,但我的目标是生成所请求的基本程序。 / p>
测试了从1到100000的所有整数,这对任何人都应该足够了。
编辑:我提到的稍微更加pythonic和更快的版本:def int_to_roman(number):
result = []
for (arabic, roman) in ROMAN:
(factor, number) = divmod(number, arabic)
result.append(roman * factor)
if number == 0:
break
return "".join(result)
答案 3 :(得分:4)
这里是一个用于整数到罗马数字转换的lambda函数,工作频率高达3999.它固定了&#34;空间的某些角落;你可能不想做的不可读的事情&#34; 。但它可能会使某些人感到高兴:
lambda a: (
"".join(reversed([
"".join([
"IVXLCDM"[int(d)+i*2]
for d in [
"", "0", "00", "000", "01",
"1", "10", "100", "1000", "02"][int(c)]])
for i,c in enumerate(reversed(str(a))) ]))
)
这种方法提供了使用算术操作的替代方法 隔离十进制数字及其位置,如OP和许多示例所做的那样。 这里的方法直接将十进制数转换为字符串。 这样,可以通过列表索引来隔离数字。数据表是公平的 压缩,不使用减法或除法。
不可否认,以给定的形式,简单地获得的任何东西都是立即的 放弃了可读性。对于没有时间拼图的人,下面是一个版本 给出了避免列表理解和lambda函数。
但我在这里解释lambda函数版本......
从后到前:
将十进制整数转换为其数字的反转字符串,并枚举 ( i )反转数字( c )。
....
for i,c in enumerate(reversed(str(a)))
....
将每个数字 c 转换回整数(范围0-9),并将其用作魔术数字字符串列表的索引。稍后会解释魔法。
....
[ "", "0", "00", "000", "01",
"1", "10", "100", "1000", "02"][int(c)]])
....
将您选择的魔术数字字符串转换为罗马数字字符串
&#34;数字&#34 ;.基本上,您现在将十进制数字表示为罗马字母
数字数字适合十进制数字的原始10位。
这是OP使用的generate_all_of_numeral
函数的目标。
....
"".join([
"IVXLCDM"[int(d)+i*2]
for d in <magic digit string>
....
以相反的顺序连接所有内容。逆转是顺序 的数字,但 中的数字(&#34;数字&#34;?)不受影响。
lambda a: (
"".join(reversed([
<roman-numeral converted digits>
]))
现在,关于魔术字符串列表。它允许选择合适的 对于十进制数字可以占用的每个不同的10个位置,罗马数字串(最多四个,每个是0,1或2三种类型之一)的字符串。
- 0 - &gt; &#34;&#34 ;;罗马数字不显示零。
- 1 - &gt; &#34; 0&#34 ;; 0 + 2 * i映射到I,X,C或M - >我,X,C或M.
- 2 - &gt; &#34; 00&#34 ;;喜欢1,x2 - &gt; II,XX,CC,MM。
- 3 - &gt; &#34; 000&#34 ;;喜欢1,x3 - &gt; III,XXX,CCC,MMM。
- 4 - &gt; &#34; 01&#34 ;;比如1,然后1 + 2 * i映射到V,L或D - > IV,XL,CD。
- 5 - &gt; &#34; 1&#34 ;;映射到奇数罗马数字数字 - &gt; V,L,D。
- 6 - &gt; &#34; 10&#34 ;;反向4 - > VI,LX,DC。
- 7 - &gt; &#34; 100&#34 ;;添加另一个I / X / C - &gt; VII LXX,DCC
- 8 - &gt; &#34 1000&#34 ;;添加另一个I / X / C - &gt; VIII,LXXX,DCCC
- 9 - &gt; &#34; 02&#34 ;;喜欢1,加上接下来的10级升级(2 + i * 2) - &gt; IX,XC,CM。
4000以上,这将引发异常。 &#34; MMMM&#34; = 4000,但是这个 不再匹配模式,打破了算法的假设。
...如上所述......
def int_to_roman(a):
all_roman_digits = []
digit_lookup_table = [
"", "0", "00", "000", "01",
"1", "10", "100", "1000", "02"]
for i,c in enumerate(reversed(str(a))):
roman_digit = ""
for d in digit_lookup_table[int(c)]:
roman_digit += ("IVXLCDM"[int(d)+i*2])
all_roman_digits.append(roman_digit)
return "".join(reversed(all_roman_digits))
我再次遗漏了异常陷阱,但至少现在有一个地方可以将其内联。
答案 4 :(得分:3)
我将此url称为在线小数到罗马转换。如果我们将小数范围扩展到3,999,999,那么@Manhattan给出的脚本将无效。这是正确的脚本,范围为3,999,999。
def int_to_roman(num):
_values = [
1000000, 900000, 500000, 400000, 100000, 90000, 50000, 40000, 10000, 9000, 5000, 4000, 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
_strings = [
'M', 'C', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
result = ""
decimal = num
while decimal > 0:
for i in range(len(_values)):
if decimal >= _values[i]:
if _values[i] > 1000:
result += u'\u0304'.join(list(_strings[i])) + u'\u0304'
else:
result += _strings[i]
decimal -= _values[i]
break
return result
示例输出:
答案 5 :(得分:2)
Laughing Man的方法有效。使用有序字典很聪明。但是每次调用函数时,他的代码都会重新创建有序字典,并且在函数内,在每次递归调用中,函数都会从顶部逐步执行整个有序字典。此外,divmod返回商和余数,但不使用余数。更直接的方法如下。
var data=require('./mapfeedback_testdata.json');
element.all(by.css(data.road_button)).click();
检查结果:
def _getRomanDictOrdered():
#
from collections import OrderedDict
#
dIntRoman = OrderedDict()
#
dIntRoman[1000] = "M"
dIntRoman[900] = "CM"
dIntRoman[500] = "D"
dIntRoman[400] = "CD"
dIntRoman[100] = "C"
dIntRoman[90] = "XC"
dIntRoman[50] = "L"
dIntRoman[40] = "XL"
dIntRoman[10] = "X"
dIntRoman[9] = "IX"
dIntRoman[5] = "V"
dIntRoman[4] = "IV"
dIntRoman[1] = "I"
#
return dIntRoman
_dIntRomanOrder = _getRomanDictOrdered() # called once on import
def getRomanNumeralOffInt( iNum ):
#
lRomanNumerals = []
#
for iKey in _dIntRomanOrder:
#
if iKey > iNum: continue
#
iQuotient = iNum // iKey
#
if not iQuotient: continue
#
lRomanNumerals.append( _dIntRomanOrder[ iKey ] * iQuotient )
#
iNum -= ( iKey * iQuotient )
#
if not iNum: break
#
#
return ''.join( lRomanNumerals )
答案 6 :(得分:1)
Python 包 roman
(repository) 可用于在 roman numerals 之间进行转换:
import roman
r = roman.toRoman(5)
assert r == 'V', r
n = roman.fromRoman('V')
assert n == 5, n
可以使用 Python Package Index (PyPI) package manager 从 pip
安装此软件包:
pip install roman
答案 7 :(得分:1)
这是我的方法
def itr(num):
dct = { 1: "I", 4: "IV", 5: "V", 9: "IX", 10: "X", 40: "XL", 50: "L", 90: "XC", 100: "C", 400: "CD", 500: "D", 900: "CM", 1000: "M" }
if(num in dct):
return dct[num]
for i in [1000,100,10,1]:
for j in [9*i, 5*i, 4*i, i]:
if(num>=j):
return itr(j) + itr(num-j)
答案 8 :(得分:1)
有趣的问题。有几种方法,但尚未见过。我们可以将执行时间换为内存,并减少潜在的讨厌的算术错误(一对一,int与float div等)。
每个阿拉伯数字(1s,10s,100s等)都转换为唯一的罗马序列。因此,只需使用查找表即可。
ROMAN = {
0 : ['', 'm', 'mm', 'mmm'],
1 : ['', 'c', 'cc', 'ccc', 'cd', 'd', 'dc', 'dcc', 'dccc', 'cm'],
2 : ['', 'x', 'xx', 'xxx', 'xl', 'l', 'lx', 'lxx', 'lxxx', 'xc'],
3 : ['', 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix'],
}
def to_roman (num, lower = True):
'''Return the roman numeral version of num'''
ret = ''
digits = '%04d' % num
for pos, digit in enumerate (digits):
ret += ROMAN [pos] [int (digit)]
return lower and ret or ret.upper ()
您可以添加对0> num> 4000的检查,但不是必需的,因为在对'-'或索引超出范围进行int转换时查找将失败。我更喜欢小写字母,但也可以使用大写字母。
数字选择可以算术完成,但是算法变得有些棘手。查找既简单又有效。
答案 9 :(得分:1)
我观察到,在大多数答案中,人们会存储多余的符号,例如"IX" for 9
,"XL" for 40
等等。
这忽略了罗马转换的主要精髓。
在我实际粘贴代码之前,这是一个小的介绍和算法。
罗马数字的原始图案使用符号I,V和X(1,5和10)作为简单的计数标记。 1(I)的每个标记添加单位值最多5(V),然后添加到(V)以使数字从6到9:
I,II,III,IIII,V,VI,VII,VIII,VIIII,X。
4(IIII)和9(VIIII)的数字证明是有问题的,并且通常用IV(一个小于5)和IX(一个小于10)代替。罗马数字的这一特征称为减法符号。
1到10之间的数字(包括4和9的减法表示法)用罗马数字表示如下:
I,II,III,IV,V,VI,VII,VIII,IX,X。
系统基本上是十进制的,数十和数百遵循相同的模式: 因此10到100(数十,用X代替我,L取代V和C取代X):
X,XX,XXX,XL,L,LX,LXX,LXXX,XC,C。Roman Numerals - Wikipedia
因此,可以从上面的介绍中得出的主要逻辑是,我们将根据罗马人使用的文字的值去除位置值并执行除法。
让我们开始基础示例。我们将文字的整数列表设为[10, 5, 1]
1/10 = 0.1(没多大用处)
1/5 = 0.2(也没有多大用处)
1/1 = 1.0(嗯,我们得到了一些东西!)
CASE 1 :因此,如果商= = 1,则打印与整数对应的文字。因此,最好的数据结构是字典。 {10: "X", 5: "V", 1:"I"}
&#34; I&#34;将被打印。
2/10 = 0.2
2/5 = 0.4
2/1 = 2
案例2 :所以,如果是商数&gt; 1,打印对应于整数的文字,并将其从数字中减去。 这使它成为1,它落到CASE 1。 &#34; II&#34;打印出来。
3/10 = 0.3
3/5 = 0.6
3/1 = 3
所以,案例2:&#34;我&#34;,案例2:&#34; II&#34;和案例1:&#34; III&#34;
CASE 3 :添加1并检查商数== 1.
(4 + 1)/ 10 = 0.5
(4 + 1)/ 5 = 1
因此,我们首先减去除数和数字并打印对应于结果的文字,然后是除数。 5-4 = 1,因此&#34; IV&#34;将被打印。
(9 + 1)/ 10 == 1
10-9 = 1。打印&#34;我&#34;,打印&#34; X&#34;,即&#34; IX&#34;
这也延伸到了十分之一和百分之一。
(90 +(10 ^ 1))/ 100 = 1.
打印100-90 =&#34; X&#34;,然后是100 =&#34; C&#34;。
(400 +(10 ^ 2))/ 500 = 1。
打印500-400 =&#34; C&#34;,然后是500 =&#34; D&#34;。
我们在这里需要的最后一件事是,提取位置值。例如:449应该产生400,40,9。
这可以通过去除减去10 ^(位置-1)的模数然后取10 ^位的模数来实现。
Ex:449,position = 2:449%(10 ^ 1)= 9 - > 449-9 - &gt; 440%(10 ^ 2)= 40。
'''
Created on Nov 20, 2017
@author: lu5er
'''
n = int(input())
ls = [1000, 500, 100, 50, 10, 5, 1]
st = {1000:"M", 500:"D", 100:"C", 50:"L", 10:"X", 5:"V", 1:"I"}
rem = 0
# We traverse the number from right to left, extracting the position
for i in range(len(str(n)), 0, -1):
pos = i # stores the current position
num = (n-n%(10**(pos-1)))%(10**pos) # extracts the positional values
while(num>0):
for div in ls:
# CASE 1: Logic for 1, 5 and 10
if num/div == 1:
#print("here")
print(st[div], end="")
num-=div
break
# CASE 2: logic for 2, 3, 6 and 8
if num/div > 1:
print(st[div],end="")
num-=div
break
# CASE 3: Logic for 4 and 9
if (num+(10**(pos-1)))/div == 1:
print(st[div-num], end="")
print(st[div], end="")
num-=div
break
输出测试
99
XCIX
499
CDXCIX
1954
MCMLIV
1990
MCMXC
2014
MMXIV
35
XXXV
994
CMXCIV
答案 10 :(得分:0)
我认为这是最简单的方法。罗马数字的范围是 1 到 3999。
def toRomanNumeral(n):
NumeralMatrix = [
["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],
["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"],
["", "M", "MM", "MMM"]
]
# The above matrix helps us to write individual digits of the input as roman numeral.
# Rows corresponds to the place of the digit (ones, tens, hundreds, etc).
# Column corresponds to the digit itself.
rn = ""
d = []
# d is an array to store the individual digits of the input
while (n!=0):
d.append(n%10)
n =int(n/10)
for i in range(len(d), 0, -1):
rn += NumeralMatrix[i-1][d[i-1]]
# [i-1] is the digit's place (0 - ones, 1 - tens, etc)
# [d[i-1]] is the digit itself
return rn
print(toRomanNumeral(49))
# XLIX
答案 11 :(得分:0)
这是我解决这个问题的方法。首先将给定的数字转换为字符串,以便随后我们可以轻松地对每个数字进行迭代以获得对应数字的罗马部分。为了获得每个数字的罗马部分,我将每个小数点后的罗马字母分为1和5,因此基于小数点后的罗马字符列表看起来像[['I','V'],['X ','L'],['C','D'],['M']],其中字符遵循一个或几个,数十,数百和数千的顺序。
因此,我们有数字要循环显示,并且罗马数字以小数点后的每个顺序表示,我们只需要使用上述字符列表准备数字0-9。变量“ order”会根据当前数字的小数位选择正确的字符集,这将在我们从最高的小数位到最低的位时自动处理。以下是完整的代码:
def getRomanNumeral(num):
# ---------- inner function -------------------
def makeRomanDigit(digit, order):
chars = [['I', 'V'], ['X', 'L'], ['C', 'D'], ['M']]
if(digit == 1):
return chars[order][0]
if(digit == 2):
return chars[order][0] + chars[order][0]
if(digit == 3):
return chars[order][0] + chars[order][0] + chars[order][0]
if(digit == 4):
return chars[order][0] + chars[order][1]
if(digit == 5):
return chars[order][1]
if(digit == 6):
return chars[order][1] + chars[order][0]
if(digit == 7):
return chars[order][1] + chars[order][0] + chars[order][0]
if(digit == 8):
return chars[order][1] + chars[order][0] + chars[order][0] + chars[order][0]
if(digit == 9):
return chars[order][0] + chars[order+1][0]
if(digit == 0):
return ''
#--------------- main -----------------
str_num = str(num)
order = len(str_num) - 1
result = ''
for digit in str_num:
result += makeRomanDigit(int(digit), order)
order-=1
return result
一些测试:
getRomanNumeral(112)
'CXII'
getRomanNumeral(345)
'CCCXLV'
getRomanNumeral(591)
'DXCI'
getRomanNumeral(1000)
'M'
我知道解决该问题的代码或方法可以做很多改进,但这是我第一次尝试解决此问题。
答案 12 :(得分:0)
我产生了一个适用于任何int> = 0的答案:
将以下内容另存为romanize.py
def get_roman(input_number: int, overline_code: str = '\u0305') -> str:
"""
Recursive function which returns roman numeral (string), given input number (int)
>>> get_roman(0)
'N'
>>> get_roman(3999)
'MMMCMXCIX'
>>> get_roman(4000)
'MV\u0305'
>>> get_roman(4000, overline_code='^')
'MV^'
"""
if input_number < 0 or not isinstance(input_number, int):
raise ValueError(f'Only integers, n, within range, n >= 0 are supported.')
if input_number <= 1000:
numeral, remainder = core_lookup(input_number=input_number)
else:
numeral, remainder = thousand_lookup(input_number=input_number, overline_code=overline_code)
if remainder != 0:
numeral += get_roman(input_number=remainder, overline_code=overline_code)
return numeral
def core_lookup(input_number: int) -> (str, int):
"""
Returns highest roman numeral (string) which can (or a multiple thereof) be looked up from number map and the
remainder (int).
>>> core_lookup(3)
('III', 0)
>>> core_lookup(999)
('CM', 99)
>>> core_lookup(1000)
('M', 0)
"""
if input_number < 0 or input_number > 1000 or not isinstance(input_number, int):
raise ValueError(f'Only integers, n, within range, 0 <= n <= 1000 are supported.')
basic_lookup = NUMBER_MAP.get(input_number)
if basic_lookup:
numeral = basic_lookup
remainder = 0
else:
multiple = get_multiple(input_number=input_number, multiples=NUMBER_MAP.keys())
count = input_number // multiple
remainder = input_number % multiple
numeral = NUMBER_MAP[multiple] * count
return numeral, remainder
def thousand_lookup(input_number: int, overline_code: str = '\u0305') -> (str, int):
"""
Returns highest roman numeral possible, that is a multiple of or a thousand that of which can be looked up from
number map and the remainder (int).
>>> thousand_lookup(3000)
('MMM', 0)
>>> thousand_lookup(300001, overline_code='^')
('C^C^C^', 1)
>>> thousand_lookup(30000002, overline_code='^')
('X^^X^^X^^', 2)
"""
if input_number <= 1000 or not isinstance(input_number, int):
raise ValueError(f'Only integers, n, within range, n > 1000 are supported.')
num, k, remainder = get_thousand_count(input_number=input_number)
numeral = get_roman(input_number=num, overline_code=overline_code)
numeral = add_overlines(base_numeral=numeral, num_overlines=k, overline_code=overline_code)
# Assume:
# 4000 -> MV^, https://en.wikipedia.org/wiki/4000_(number)
# 6000 -> V^M, see https://en.wikipedia.org/wiki/6000_(number)
# 9000 -> MX^, see https://en.wikipedia.org/wiki/9000_(number)
numeral = numeral.replace(NUMBER_MAP[1] + overline_code, NUMBER_MAP[1000])
return numeral, remainder
def get_thousand_count(input_number: int) -> (int, int, int):
"""
Returns three integers defining the number, number of thousands and remainder
>>> get_thousand_count(999)
(999, 0, 0)
>>> get_thousand_count(1001)
(1, 1, 1)
>>> get_thousand_count(2000002)
(2, 2, 2)
"""
num = input_number
k = 0
while num >= 1000:
k += 1
num //= 1000
remainder = input_number - (num * 1000 ** k)
return num, k, remainder
def get_multiple(input_number: int, multiples: iter) -> int:
"""
Given an input number(int) and a list of numbers, finds the number in list closest (rounded down) to input number
>>> get_multiple(45, [1, 2, 3])
3
>>> get_multiple(45, [1, 2, 3, 44, 45, 46])
45
>>> get_multiple(45, [1, 4, 5, 9, 10, 40, 50, 90])
40
"""
options = sorted(list(multiples) + [input_number])
return options[options.index(input_number) - int(input_number not in multiples)]
def add_overlines(base_numeral: str, num_overlines: int = 1, overline_code: str = '\u0305') -> str:
"""
Adds overlines to input base numeral (string) and returns the result.
>>> add_overlines(base_numeral='II', num_overlines=1, overline_code='^')
'I^I^'
>>> add_overlines(base_numeral='I^I^', num_overlines=1, overline_code='^')
'I^^I^^'
>>> add_overlines(base_numeral='II', num_overlines=2, overline_code='^')
'I^^I^^'
"""
return ''.join([char + overline_code*num_overlines if char.isalnum() else char for char in base_numeral])
def gen_number_map() -> dict:
"""
Returns base number mapping including combinations like 4 -> IV and 9 -> IX, etc.
"""
mapping = {
1000: 'M',
500: 'D',
100: 'C',
50: 'L',
10: 'X',
5: 'V',
1: 'I',
0: 'N'
}
for exponent in range(3):
for num in (4, 9,):
power = 10 ** exponent
mapping[num * power] = mapping[1 * power] + mapping[(num + 1) * power]
return mapping
NUMBER_MAP = gen_number_map()
if __name__ == '__main__':
import doctest
doctest.testmod(verbose=True, raise_on_error=True)
# Optional extra tests
# doctest.testfile('test_romanize.txt', verbose=True)
这里有一些额外的测试,以防万一。 将以下内容保存为与romanize.py相同的目录中的test_romanize.txt:
The ``romanize`` module
=======================
The ``get_roman`` function
--------------------------
Import statement:
>>> from romanize import get_roman
Tests:
>>> get_roman(0)
'N'
>>> get_roman(6)
'VI'
>>> get_roman(11)
'XI'
>>> get_roman(345)
'CCCXLV'
>>> get_roman(989)
'CMLXXXIX'
>>> get_roman(989000000, overline_code='^')
'C^^M^^L^^X^^X^^X^^M^X^^'
>>> get_roman(1000)
'M'
>>> get_roman(1001)
'MI'
>>> get_roman(2000)
'MM'
>>> get_roman(2001)
'MMI'
>>> get_roman(900)
'CM'
>>> get_roman(4000, overline_code='^')
'MV^'
>>> get_roman(6000, overline_code='^')
'V^M'
>>> get_roman(9000, overline_code='^')
'MX^'
>>> get_roman(6001, overline_code='^')
'V^MI'
>>> get_roman(9013, overline_code='^')
'MX^XIII'
>>> get_roman(70000000000, overline_code='^')
'L^^^X^^^X^^^'
>>> get_roman(9000013, overline_code='^')
'M^X^^XIII'
>>> get_roman(989888003, overline_code='^')
'C^^M^^L^^X^^X^^X^^M^X^^D^C^C^C^L^X^X^X^V^MMMIII'
The ``get_thousand_count`` function
--------------------------
Import statement:
>>> from romanize import get_thousand_count
Tests:
>>> get_thousand_count(13)
(13, 0, 0)
>>> get_thousand_count(6013)
(6, 1, 13)
>>> get_thousand_count(60013)
(60, 1, 13)
>>> get_thousand_count(600013)
(600, 1, 13)
>>> get_thousand_count(6000013)
(6, 2, 13)
>>> get_thousand_count(999000000000000000000000000999)
(999, 9, 999)
>>> get_thousand_count(2005)
(2, 1, 5)
>>> get_thousand_count(2147483647)
(2, 3, 147483647)
The ``core_lookup`` function
--------------------------
Import statement:
>>> from romanize import core_lookup
Tests:
>>> core_lookup(2)
('II', 0)
>>> core_lookup(6)
('V', 1)
>>> core_lookup(7)
('V', 2)
>>> core_lookup(19)
('X', 9)
>>> core_lookup(900)
('CM', 0)
>>> core_lookup(999)
('CM', 99)
>>> core_lookup(1000)
('M', 0)
>>> core_lookup(1000.2)
Traceback (most recent call last):
ValueError: Only integers, n, within range, 0 <= n <= 1000 are supported.
>>> core_lookup(10001)
Traceback (most recent call last):
ValueError: Only integers, n, within range, 0 <= n <= 1000 are supported.
>>> core_lookup(-1)
Traceback (most recent call last):
ValueError: Only integers, n, within range, 0 <= n <= 1000 are supported.
The ``gen_number_map`` function
--------------------------
Import statement:
>>> from romanize import gen_number_map
Tests:
>>> gen_number_map()
{1000: 'M', 500: 'D', 100: 'C', 50: 'L', 10: 'X', 5: 'V', 1: 'I', 0: 'N', 4: 'IV', 9: 'IX', 40: 'XL', 90: 'XC', 400: 'CD', 900: 'CM'}
The ``get_multiple`` function
--------------------------
Import statement:
>>> from romanize import get_multiple
>>> multiples = [0, 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000]
Tests:
>>> get_multiple(0, multiples)
0
>>> get_multiple(1, multiples)
1
>>> get_multiple(2, multiples)
1
>>> get_multiple(3, multiples)
1
>>> get_multiple(4, multiples)
4
>>> get_multiple(5, multiples)
5
>>> get_multiple(6, multiples)
5
>>> get_multiple(9, multiples)
9
>>> get_multiple(13, multiples)
10
>>> get_multiple(401, multiples)
400
>>> get_multiple(399, multiples)
100
>>> get_multiple(100, multiples)
100
>>> get_multiple(99, multiples)
90
The ``add_overlines`` function
--------------------------
Import statement:
>>> from romanize import add_overlines
Tests:
>>> add_overlines('AB')
'A\u0305B\u0305'
>>> add_overlines('A\u0305B\u0305')
'A\u0305\u0305B\u0305\u0305'
>>> add_overlines('AB', num_overlines=3, overline_code='^')
'A^^^B^^^'
>>> add_overlines('A^B^', num_overlines=1, overline_code='^')
'A^^B^^'
>>> add_overlines('AB', num_overlines=3, overline_code='\u0305')
'A\u0305\u0305\u0305B\u0305\u0305\u0305'
>>> add_overlines('A\u0305B\u0305', num_overlines=1, overline_code='\u0305')
'A\u0305\u0305B\u0305\u0305'
>>> add_overlines('A^B', num_overlines=3, overline_code='^')
'A^^^^B^^^'
>>> add_overlines('A^B', num_overlines=0, overline_code='^')
'A^B'
答案 13 :(得分:0)
此罗马数字的代码不会检查错误的字母等错误,只是用于完美的罗马数字字母
roman_dict = {'M':1000, 'CM':900, 'D':500, 'CD':400, 'C':100, 'XC':90,
'L':50, 'XL':40, 'X':10, 'IX':9, 'V':5, 'IV':4,'I':1}
roman = input('Enter the roman numeral: ').upper()
roman_initial = roman # used to retain the original roman figure entered
lst = []
while roman != '':
if len(roman) > 1:
check = roman[0] + roman[1]
if check in roman_dict and len(roman) > 1:
lst.append(check)
roman = roman[roman.index(check[1])+1:]
else:
if check not in roman_dict and len(roman) > 1:
lst.append(check[0])
roman = roman[roman.index(check[0])+1:]
else:
if len(roman)==1:
check = roman[0]
lst.append(check[0])
roman = ''
if lst != []:
Sum = 0
for i in lst:
if i in roman_dict:
Sum += roman_dict[i]
print('The roman numeral %s entered is'%(roman_initial),Sum)
答案 14 :(得分:0)
这里有一个更简单的方法,我遵循了基本的转换方法here
请在下面找到代码:
input = int(raw_input()) # enter your integerval from keyboard
Decimals =[1,4,5,9,10,40,50,90,100,400,500,900,1000]
Romans =['I','IV','V','IX','X','XL','L','XC','C','CD','D','CM','M']
romanletters= [] # empty array to fill each corresponding roman letter from the Romans array
while input != 0:
# we use basic formula of converstion, therefore input is substracted from
# least maximum similar number from Decimals array until input reaches zero
for val in range (len(Decimals)):
if input >= Decimals[val]:
decimal = Decimals[val]
roman = Romans[val]
difference = input - decimal
romanletters.append(roman)
input = difference
dec_to_roman = ''.join(romanletters) # concatinate the values
print dec_to_roman
答案 15 :(得分:0)
开始从A减去1000,900 ...到1并在找到正数时停止)在A未变为0时重复。
def intToRoman(self, A):
l=[[1,'I'],[4,'IV'],[5,'V'],[9,'IX'],[10,'X'],[40,'XL'],[50,'L'],
[90,'XC'],[100,'C'],[400,'CD'],[500,'D'],[900,'CM'],[1000,'M']]
ans=""
while(A>0):
for i,j in l[::-1]:
if A-i>=0:
ans+=j
A=A-i
break
return ans
答案 16 :(得分:0)
我从我的 GitHub 中抓取了这个(你可以在那里找到更详细的版本)。该函数具有固定的计算时间并且不使用外部库。它适用于 0 到 1000 之间的所有整数。
def to_roman(n):
try:
if n >= 0 and n <= 1000:
d = [{'0':'','1':'M'},
{'0':'','1':'C','2':'CC','3':'CCC','4':'DC','5':'D',
'6':'DC','7':'DCC','8':'DCCC','9':'MC'},
{'0':'','1':'X','2':'XX','3':'XXX','4':'XL','5':'L',
'6':'LX','7':'LXX','8':'LXXX','9':'CX'},
{'0':'','1':'I','2':'II','3':'III','4':'IV','5':'V',
'6':'VI','7':'VII','8':'VIII','9':'IX'}]
x = str('0000' + str(n))[-4:]
r = ''
for i in range(4):
r = r + d[i][x[i]]
return r
else:
return '`n` is out of bounds.'
except:
print('Is this real life?\nIs `n` even an integer?')
输入 n=265
的输出:
>>> to_roman(265)
'CCLXV'
答案 17 :(得分:0)
def convert_to_roman(number, rom_denom, rom_val):
'''Recursive solution'''
#Base case
if number == 0:
return ''
else:
rom_str = (rom_denom[0] * (number//rom_val[0])) + convert_to_roman(number %
rom_val[0], rom_denom[1:], rom_val[1:]) #Recursive call
return rom_str
rom_denom = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']
rom_val = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
number = int(input("Enter numeral to convert: "))
rom_str = convert_to_roman(number, rom_denom, rom_val)
print(rom_str)
答案 18 :(得分:0)
def convert_to_roman(num):
# print(num)
roman=""
while(num!=0):
if num in range(1000,5000):
roman+="M"*(num//1000)
num-=(num//1000)*1000
if num in range(900,1000): #range(a,b) works from a to b-1 here from 900->999
roman+="CM"
num-=900
if num in range(500,900):
roman+="D"
num-=500
if num in range(400,500):
roman+="CD"
num-=400
if num in range(100,400):
roman+="C"*(num//100)
num-=100*(num//100)
if num in range(90,100):
roman+="XC"
num-=90
if num in range(50,90):
roman+="L"
num-=50
if num in range(40,50):
roman+="XL"
num-=40
if num in range(10,40):
roman+="X"*(num//10)
num-=10*(num//10)
if num==9:
roman+="IX"
num-=9
if num in range(5,9):
roman+="V"
num-=5
if num ==4:
roman+="IV"
num-=4
if num ==3:
roman+="III"
num-=3
if num ==2:
roman+="II"
num-=2
if num ==1:
roman+="I"
num-=1
# print(num)
return roman
#Start writing your code here
num=888
print(num,":",convert_to_roman(num))
答案 19 :(得分:0)
另一种方式。 我用罗马符号写了递归循环,所以最大递归深度等于罗马元组的长度:
ROMAN = ((1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
(100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
(10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I'))
def get_romans(number):
return do_recursive(number, 0, '')
def do_recursive(number, index, roman):
while number >= ROMAN[index][0]:
number -= ROMAN[index][0]
roman += ROMAN[index][1]
if number == 0:
return roman
return check_recursive(number, index + 1, roman)
if __name__ == '__main__':
print(get_romans(7))
print(get_romans(78))
答案 20 :(得分:0)
我正在通过kata练习来完成此转换,然后我想出了一个利用Python字符串操作的解决方案:
from collections import namedtuple
Abbreviation = namedtuple('Abbreviation', 'long short')
abbreviations = [
Abbreviation('I' * 1000, 'M'),
Abbreviation('I' * 500, 'D'),
Abbreviation('I' * 100, 'C'),
Abbreviation('I' * 50, 'L'),
Abbreviation('I' * 10, 'X'),
Abbreviation('I' * 5, 'V'),
Abbreviation('DCCCC', 'CM'),
Abbreviation('CCCC', 'CD'),
Abbreviation('LXXXX', 'XC'),
Abbreviation('XXXX', 'XL'),
Abbreviation('VIIII', 'IX'),
Abbreviation('IIII', 'IV')
]
def to_roman(arabic):
roman = 'I' * arabic
for abbr in abbreviations:
roman = roman.replace(abbr.long, abbr.short)
return roman
我喜欢它的简单性!无需模运算,条件运算或多个循环。当然,您也不需要namedtuple
;您可以改用普通元组或列表。
答案 21 :(得分:0)
这是我的递归函数方法,用于将数字转换为罗马数字
def solution(n):
# TODO convert int to roman string
string=''
symbol=['M','D','C','L','X','V','I']
value = [1000,500,100,50,10,5,1]
num = 10**(len(str(n))-1)
quo = n//num
rem=n%num
if quo in [0,1,2,3]:
string=string+symbol[value.index(num)]*quo
elif quo in [4,5,6,7,8]:
tem_str=symbol[value.index(num)]+symbol[value.index(num)-1]
+symbol[value.index(num)]*3
string=string+tem_str[(min(quo,5)-4):(max(quo,5)-3)]
else:
string=string+symbol[value.index(num)]+symbol[value.index(num)-2]
if rem==0:
return string
else:
string=string+solution(rem)
return string
print(solution(499))
print(solution(999))
print(solution(2456))
print(solution(2791))
CDXCIX
CMXCIX
MMCDLVI
MMDCCXCI
答案 22 :(得分:0)
您必须使symbolCount成为全局变量。并在打印方法中使用()。
答案 23 :(得分:0)
roman_map = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'),
(50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]
def IntToRoman (xn):
x = xn
y = 0
Str = ""
for i, r in roman_map:
# take the number and divisible by the roman number from 1000 to 1.
y = x//i
for j in range(0, y):
# If after divisibility is not 0 then take the roman number from list into String.
Str = Str+r
# Take the remainder to next round.
x = x%i
print(Str)
return Str
测试用例:
>>> IntToRoman(3251)
MMMCCLI
'MMMCCLI'
答案 24 :(得分:0)
def test(num):
try:
if type(num) != type(1):
raise Exception("expected integer, got %s" % type(num))
if not 0 < num < 4000:
raise Exception("Argument must be between 1 and 3999")
ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
nums = ('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I')
result = ""
for i in range(len(ints)):
count = int(num / ints[i])
result += nums[i] * count
num -= ints[i] * count
print result
except Exception as e:
print e.message
答案 25 :(得分:0)
另一种方法。从4,9等开始分离出数字处理。它可以进一步简化
def checkio(data):
romans = [("I",1),("V",5),("X",10),("L",50),("C",100),("D",500),("M",1000)]
romans_rev = list(sorted(romans,key = lambda x: -x[1]))
def process_9(num,roman_str):
for (k,v) in romans:
if (v > num):
current_roman = romans[romans.index((k,v))]
prev_roman = romans[romans.index((k,v)) - 2]
roman_str += (prev_roman[0] + current_roman[0])
num -= (current_roman[1] - prev_roman[1])
break
return num,roman_str
def process_4(num,roman_str):
for (k,v) in romans:
if (v > num):
current_roman = romans[romans.index((k,v))]
prev_roman = romans[romans.index((k,v)) - 1]
roman_str += (prev_roman[0] + current_roman[0])
num -= (current_roman[1] - prev_roman[1])
break
return num,roman_str
def process_other(num,roman_str):
for (k,v) in romans_rev:
div = num // v
if ( div != 0 and num > 0 ):
roman_str += k * div
num -= v * div
break
return num,roman_str
def get_roman(num):
final_roman_str = ""
while (num > 0):
if (str(num).startswith('4')):
num,final_roman_str = process_4(num,final_roman_str)
elif(str(num).startswith('9')):
num,final_roman_str = process_9(num,final_roman_str)
else:
num,final_roman_str = process_other(num,final_roman_str)
return final_roman_str
return get_roman(data)
print(checkio(number))
答案 26 :(得分:0)
result = (result.array() < 0).select(0, result);
答案 27 :(得分:-1)
编写一个简单的代码,该代码接受数字,减少数字,并将其对应的值附加到列表中的罗马数字中,最后将其转换为字符串。这应该适用于范围1到3999
s=input("Enter String To Be Reversed:")
print(s[::-1])
答案 28 :(得分:-1)
这是一个简短的递归解决方案:
romVL = [999, 'IM', 995, 'VM', 990, 'XM', 950, 'LM', 900, 'CM', 500, 'D', 499, 'ID', 495, 'VD', 490, 'XD', 450, 'LD', 400, 'CD', 100, 'C', 99, 'IC', 95, 'VC', 90, 'XC', 50, 'L', 49, 'IL', 45, 'VL', 40, 'XL', 10, 'X', 9, 'IX', 5, 'V', 4, 'IV', 1, 'I']
def int2rom(N,V=1000,L="M",*rest):
return N//V*L + int2rom(N%V,*rest or romVL) if N else ""
示例:
int2rom(1999) 'MIM'
int2rom(1938) 'MCMXXXVIII'
int2rom(1988) 'MLMXXXVIII'
int2rom(2021) 'MMXXI'
和反向函数:
def rom2int(R):
LV = {"M":1000,"D":500,"C":100,"L":50,"X":10,"V":5,"I":1}
return sum(LV[L]*[1,-1][LV[L]<LV[N]] for L,N in zip(R,R[1:]+"I"))
答案 29 :(得分:-1)
"""
# This program will allow the user to input a number from 1 - 3999 (in english) and will translate it to Roman numerals.
# sources: http://romannumerals.babuo.com/roman-numerals-100-1000
Guys the reason why I wrote this program like that so it becomes readable for everybody.
Let me know if you have any questions...
"""
while True:
try:
x = input("Enter a positive integer from 1 - 3999 (without spaces) and this program will translated to Roman numbers: ")
inttX = int(x)
if (inttX) == 0 or 0 > (inttX):
print("Unfortunately, the smallest number that you can enter is 1 ")
elif (inttX) > 3999:
print("Unfortunately, the greatest number that you can enter is 3999")
else:
if len(x) == 1:
if inttX == 1:
first = "I"
elif inttX == 2:
first = "II"
elif inttX == 3:
first = "III"
elif inttX == 4:
first = "IV"
elif inttX == 5:
first = "V"
elif inttX == 6:
first = "VI"
elif inttX == 7:
first = "VII"
elif inttX == 8:
first = "VIII"
elif inttX == 9:
first = "IX"
print(first)
break
if len(x) == 2:
a = int(x[0])
b = int(x[1])
if a == 0:
first = ""
elif a == 1:
first = "X"
elif a == 2:
first = "XX"
elif a == 3:
first = "XXX"
elif a == 4:
first = "XL"
elif a == 5:
first = "L"
elif a == 6:
first = "LX"
elif a == 7:
first = "LXX"
elif a == 8:
first = "LXXX"
elif a == 9:
first = "XC"
if b == 0:
first1 = "0"
if b == 1:
first1 = "I"
elif b == 2:
first1 = "II"
elif b == 3:
first1 = "III"
elif b == 4:
first1 = "IV"
elif b == 5:
first1 = "V"
elif b == 6:
first1 = "VI"
elif b == 7:
first1 = "VII"
elif b == 8:
first1 = "VIII"
elif b == 9:
first1 = "IX"
print(first + first1)
break
if len(x) == 3:
a = int(x[0])
b = int(x[1])
c = int(x[2])
if a == 0:
first12 = ""
if a == 1:
first12 = "C"
elif a == 2:
first12 = "CC"
elif a == 3:
first12 = "CCC"
elif a == 4:
first12 = "CD"
elif a == 5:
first12 = "D"
elif a == 6:
first12 = "DC"
elif a == 7:
first12 = "DCC"
elif a == 8:
first12 = "DCCC"
elif a == 9:
first12 = "CM"
if b == 0:
first = ""
elif b == 1:
first = "X"
elif b == 2:
first = "XX"
elif b == 3:
first = "XXX"
elif b == 4:
first = "XL"
elif b == 5:
first = "L"
elif b == 6:
first = "LX"
elif b == 7:
first = "LXX"
elif b == 8:
first = "LXXX"
elif b == 9:
first = "XC"
if c == 1:
first1 = "I"
elif c == 2:
first1 = "II"
elif c == 3:
first1 = "III"
elif c == 4:
first1 = "IV"
elif c == 5:
first1 = "V"
elif c == 6:
first1 = "VI"
elif c == 7:
first1 = "VII"
elif c == 8:
first1 = "VIII"
elif c == 9:
first1 = "IX"
print(first12 + first + first1)
break
if len(x) == 4:
a = int(x[0])
b = int(x[1])
c = int(x[2])
d = int(x[3])
if a == 0:
first1 = ""
if a == 1:
first1 = "M"
elif a == 2:
first1 = "MM"
elif a == 3:
first1 = "MMM"
if b == 0:
first12 = ""
if b == 1:
first12 = "C"
elif b == 2:
first12 = "CC"
elif b == 3:
first12 = "CCC"
elif b == 4:
first12 = "CD"
elif b == 5:
first12 = "D"
elif b == 6:
first12 = "DC"
elif b == 7:
first12 = "DCC"
elif b == 8:
first12 = "DCCC"
elif b == 9:
first12 = "CM"
if c == 0:
first3 = ""
elif c == 1:
first3 = "X"
elif c == 2:
first3 = "XX"
elif c == 3:
first3 = "XXX"
elif c == 4:
first3 = "XL"
elif c == 5:
first3 = "L"
elif c == 6:
first3 = "LX"
elif c == 7:
first3 = "LXX"
elif c == 8:
first3 = "LXXX"
elif c == 9:
first3 = "XC"
if d == 0:
first = ""
elif d == 1:
first = "I"
elif d == 2:
first = "II"
elif d == 3:
first = "III"
elif d == 4:
first = "IV"
elif d == 5:
first = "V"
elif d == 6:
first = "VI"
elif d == 7:
first = "VII"
elif d == 8:
first = "VIII"
elif d == 9:
first = "IX"
print(first1 + first12 + first3 + first)
break
except ValueError:
print(" Please enter a positive integer! ")
答案 30 :(得分:-1)
当您使用def关键字时,您只需定义一个函数,但不要运行它。
你正在寻找的是更像这样的东西:
def generate_all_numerals(n):
...
def to_roman(n):
...
print "This program ..."
n = raw_input("Enter...")
print to_roman(n)
欢迎来到python:)