转换为罗马数字!


13

您的任务是将给定的正整数从阿拉伯数字转换为罗马数字。

当您计数到4000时,事情就会变得困难。

罗马人通过在符号上方添加一条线将该符号乘以来做到这一点1 000。但是,上划线不能完全以ASCII显示。此外,还有两次将符号乘以的上划线1 000 000,然后是三次将符号乘以的上划线1 000 000 000,等等。

因此,我决定使用括号代替上划线。

这些符号可以单独放在括号中。例如,(VI)和和(V)(I)都是的有效表示形式6 000(V)M也是6000的有效表示形式。

(I)是一种有效的表示方式1 000

测试用例

Input: 1
Output: I
Input: 2
Output: II
Input: 3
Output: III
Input: 4
Output: IV
Input: 15
Output: XV
Input: 40
Output: XL
Input: 60
Output: LX
Input: 67
Output: LXVII
Input: 400
Output: CD
Input: 666
Output: DCLXVI
Input: 3000
Output: MMM
Input: 3999
Output: MMMCMXCIX
Input: 4000
Output: M(V)
Input: 4999
Output: M(V)CMXCIX
Input: 6000
Output: (VI)
Input: 6000000
Output: ((VI))
Input: 6006000
Output: ((VI)VI)
Input: 6666666666
Output: (((VI)DCLXVI)DCLXVI)DCLXVI

计分

这是。以字节为单位的最短代码获胜。


1
为什么这不是重复的理由使规范混乱。没有IMO会更好。
Mego 2016年

我在哪里添加理由?
Leaky Nun

1
别说了。如果有人质疑它是否重复,请在评论或聊天中进行讨论。
Mego 2016年

@Mego完成。:-)
Leaky Nun

(IV)4000可接受的代表性?
尼尔

Answers:


9

Mathematica,67个字节

Fold["("<>#<>")"<>#2&,RomanNumeral[#~IntegerDigits~1000]/."N"->""]&

M通过将输入转换为基数1000并用分别转换每个数字,避免了所有麻烦RomanNumeral。然后我们通过(...)从左侧插入将它们折叠起来。

不幸的是,Mathematica代表零,N因此我们需要摆脱这些零。


1
darn mathematica及其所有内置
函数

1
@ OldBunny2800如果这仍然没有被任何一种高尔夫语言所打败,我会感到惊讶。
Martin Ender

@ OldBunny2800而要花费真钱。那很糟。
暴民埃里克(Erik the Outgolfer)

我认为@MartinBüttner RomanNumeral可以做到吗?
Leaky Nun

1
@KennyLau它的输出MMMM4000,它仅在规格下开始工作5000(然后您遇到同样的问题,4000000等等)。即使这样,它也会使用横杠而不是括号。如果可以的话,应该在挑战说明中这样说。
Martin Ender

7

JavaScript(ES6),136个字节

f=n=>n<4e3?"M1000CM900D500CD400C100XC90L50XL40X10IX9V5IV4I1".replace(/(\D+)(\d+)/g,(_,r,d)=>r.repeat(n/d,n%=d)):`(${f(n/1e3)})`+f(n%1e3)

对于4000以下的数字,请使用罗马“字母”列表及其十进制值将每个罗马“字母”重复多次。否则,递归地从除法中建立答案,并以1000为模。幸运的是,它repeat被截断了,因此我不必自己做。


3

普通Lisp,108

(defun p(n)(if(> n 0)(if(< n 4000)(format()"~@R"n)(format()"(~A)~@[~A~]"(p(floor n 1000))(p(mod n 1000))))))

不打高尔夫球

(defun p(n)
  (if (> n 0)
      (if (< n 4000)

          ;; Built-in Roman formatter (between 1 and 3999)
          (format () "~@R" n)

          ;; Divide N by 1000, as 1000*Q + R.
          ;; First print (p Q) in parentheses (recursively)
          ;; Then, if it is not NIL, the remainder R.
          (format () "(~A)~@[~A~]"
                  (p (floor n 1000))
                  (p (mod n 1000))))))

测验

两种测试给出的输出与问题所给出的输出不同:

(loop for (in out) in '((1 "I")
                        (2 "II")
                        (3 "III")
                        (4 "IV")
                        (15 "XV")
                        (40 "XL")
                        (60 "LX")
                        (67 "LXVII")
                        (400 "CD")
                        (666 "DCLXVI")
                        (3000 "MMM")
                        (3999 "MMMCMXCIX")
                        (4000 "M(V)")
                        (4999 "M(V)CMXCIX")
                        (6000 "(VI)")
                        (6000000 "((VI))")
                        (6006000 "((VI)VI)")
                        (6666666666 "(((VI)DCLXVI)DCLXVI)DCLXVI"))
   for computed = (p in)
   unless (string= out computed)
   collect (list in out computed))

=> ((4000 "M(V)" "(IV)")
    (4999 "M(V)CMXCIX" "(IV)CMXCIX"))

2

R,134

m=1000;x=scan();while(x[1]>=m)x=c(floor(x[1]/m),x[1]%%m,x[-1]);cat(rep("(",length(x)),sep="");cat(as.character(as.roman(x)),sep=")")

这几乎不是最佳选择,但我认为这个主意应该与此类似。


1

蟒蛇,188194

摆脱一些空白的-6个字节

这个挑战使我回到了我第一次学习编程的时候。

def f(x,s=zip("M CM D CD C XC L XL X IX V IV I".split(),[1e3,900,500,400,100,90,50,40,10,9,5,4,1])):
 r=""if x<4e3else"("+f(x/1e3)+")";x%=1e3
 for a,b in s:
    while x>=b:r+=a;x-=b
 return r

它可能不是最短的解决方案,但我很高兴打高尔夫球。

试试看!


1

红宝石,137个 134 130字节

返回字符串的递归函数。如果可能的话,我会尽量减少数字编码的使用,但是我不确定如何。

糟糕,现在它实际上是@Neil ES6答案的直接端口。

f=->x{(x<t=1e3)?"CM900D500CD400C100XC90L50XL40X10IX9V5IV4I1".gsub(/(\D+)(\d+)/){v=$2.to_i;s=x/v;x%=v;$1*s}:"(#{f[x/t]})#{f[x%t]}"}

1

Ruby,185161144字节

r=->i{i>(t=1e3)? "(#{r[i/t]})"+r[i%t]:(s=?I*i;"IVXXLCCDM".scan(/(.)(.)(.)/){|x,y,z|{x*5=>y,x*4=>x+y,y*2=>z,y+x+y=>x+z}.map{|x,y|s.gsub!x,y}};s)}

在原始职位发布一年多之后,我想我学到了一些高尔夫球知识。

感谢您对Value Ink的宝贵评论。


gsub可以将字符串作为第一个参数,因为s.gsub! x,y它会自动执行,所以无需在正则表达式模式中进行替换。除此之外,您可能只需要放弃a数组的分配,因为您只使用了一次,然后直接将其放入each_slice调用中。
价值墨水

"IVXXLCCDM".scan(/(.)(.)(.)/){|x,b,c|...也可以工作
价值墨水

r[x]是功能上等同于r.(x)每当stabby lambda表达式参与
值油墨

@ValueInk谢谢。这个r[x]技巧对我所有的红宝石递归高尔夫都是有用的!
MegaTom

1

TCL 134字节

proc f r {
set map {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+}
expr [string map $map $r]0}

在这里尝试:https : //rextester.com/BJC92885

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.