罗马数字线段


10

编写一个程序或函数,接受一个范围为1..3999的整数作为输入,并返回用标准罗马数字表示该整数所需的线段数(因此,您将使用XL,但不使用VM)。例子:

   1 -> 1
   4 -> 3
   5 -> 2
   9 -> 3
  10 -> 2
  40 -> 4
  50 -> 2
  90 -> 3
 100 -> 1
 400 -> 3
 500 -> 2
 900 -> 5
1000 -> 4

罗马数字转换建宏允许的,但你可以通过反复从上面的列表中减去剩余数量最多的解决问题没有他们。例如:1234 = 4 +1 +1 +1 2 2 2 + 2 + 3 = 15。

这是,因此最短的程序为准。


为什么10个两个线段而不是四个?编写X时,通常只写两行,但这些行的交点难道不成四段吗?
Alex A.

@AlexA。线段的定义通常类似于:“遵循两点之间最短路径的点集”。似乎没有任何理由基于此剪切X,您只需要两组端点即可对其进行定义。(假设罗马人主要是在欧几里得几何上写的)
FryAmTheEggman

@FryAmTheEggman嗯。很高兴知道,谢谢。
Alex A.

Answers:


2

Pyth,92 76 70字节

KsMc."/9hæ²z³Þ§ªW×Oû[Tnè,O¤"\/WQ=Q-Q=Nef!>TQ%2K aY@KhxKN;sY

在这里尝试!

感谢@FryAmTheEggman提供的一些字符串打包建议,为我节省了一些字节!

我仍然想知道是否存在一种数学方法来编码此列表。会尝试找出答案。

说明

这使用给定的算法。K包含给定的列表,其中的数字和相应的线段数交替显示。通过拆分打包字符串来构造此列表,该打包字符串将解码为0/0/1/1/4/3/5/2/9/3/10/2/40/4/50/2/90/3/100/1/400/3/500/2/900/5/1000/4/然后将每个元素映射为整数。

KsMc。“ ...” \ / WQ = QQ = Nef!> TQ%2K aY @ KhxKN; sY#Q =输入

   c。“ ...” \ /#在/上分割字符串
KsM#将每个数字映射到int并分配给K
            WQ#而Q!= 0
                     f%2K#仅取K的每个第二元素并用T过滤
                      !> TQ#T <= Q
                  = Ne#取该元素的最后一个元素并将其分配给N
              = QQ#Q = Q-N
                                   xKN#N在K中首次出现的索引
                                  h#增加该索引,因为我们要线段
                              aA @ K#从该索引获取线段并将其附加到Y
                                      ; sY#结束循环并打印Y中所有线段的总和

3

C,148129个字符

d,x,n[]={1000,900,500,400,100,90,50,40,10,9,5,4,1,4,5,2,3,1,3,2,4,2,3,2,3,1};f(c){while(d+=(c/n[x])*n[x+13],c%=n[x++]);return d;}

我的第一个代码高尔夫球:^)。由于问题表明我可以使用一个函数,因此我将main更改为一个函数以修剪一些字符(最重要的是:将c作为参数而不是scanf传递)

开箱

d,x,n[]={1000,900,500,400,100,90,50,40,10,9,5,4,1,4,5,2,3,1,3,2,4,2,3,2,3,1};
f(c){
  while(d+=(c/n[x])*n[x+13],
        c%=n[x++]);
  return d;
}

2

Mathematica,80 72字节

Tr[Characters[#~IntegerString~"Roman"]/.{"I"|"C"->1,"M"->4,_String->2}]&

匿名函数只是将数字转换为罗马数字,将每个字符替换为其段数,然后取总和。


2

视网膜,128字节

。+
$ *
1 {1000}
t'
1 {900}
d
1 {500}
d
1 {400}
Ť
1 {100}
'
1 {90}
Ť
1 {50}
d
1 {40}
t'
1 {10}
d
1 {9}
Ť
1 {5}
d
1 {4}
Ť
1个
'
Ť
d'
d
''
'+
$ .0

简单更换,直至无可替代。然后计算撇号,这就是我们的线段数。

如果允许以一进制形式输入和输出,则为115个字节(尽管谁想输入1234个?)。

在线尝试!
在线尝试!(一元IO)


2

Python 3,95个字节

def f(a,b=0):
 for e in'᝴ᔝ஺ॣəȟĮô>9 ':e=ord(e);d=e//6;b+=a//d*(e%6);a%=d
 return b

Unicode字符串由以下代码点组成:

6004 5405 3002 2403 601 543 302 244 62 57 32 27 7

如果您将该字符串转换为字节文字,则可以省略e=ord(e);
xsot

我认为这不适用于我的情况。我需要一个Unicode字符串:(即我遍历码点在该字符串,没有结束的字节数。
林恩

1
哦,我明白了。您介意提供字符串的十六进制转储吗?它在我的手机上无法正确显示。
xsot

1

Java,152个字节

因为,你知道,Java。

n->{int c=0;int[]r={999,4,899,5,499,2,399,3,99,1,89,3,49,2,39,4,9,2,8,3,4,2,3,3,0,1};for(int i=0;i<26;i+=2)while(n>r[i]){n-=r[i]+1;c+=r[i+1];}return c;}

给定算法的简单文字实现。数组打包转换信息:偶数索引比罗马数字小1,奇数索引是该数字的计数。

这是一个带int/ 返回的lambda Integer。包括IntUnaryOperatorUnaryOperator<Integer>


1

JavaScript(ES6),79个字节

n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4

字符串代表单位的线段数,十位数和百位数。(千位数只是千位数的四倍。)此方法似乎比其他选项(例如问题中建议的算法)短。

编辑:由于@ user81655,节省了2个字节。


这是一个很酷的算法。重新安排演员表也可以节省2个字节:n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4
user81655 '16

@ user81655哦,这很好:将+s 更改为-s可以删除前导+,但是随后分组又节省了一个字节。
尼尔,
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.