外观顺序:罗马数字版


20

挑战说明

我们遇到了一些涉及外观序列的挑战。快速提醒:

  • 序列开头1
  • 该序列的后续项是通过枚举上一项中的每组重复数字而产生的,

因此,前几个术语是:

1        "one"
11       "one one" (we look at the previous term)
21       "two ones"
1211     "one two, one one"
111221   "one one, one two, two ones"
312211   "three ones, two twos, one one"

现在让我们做同样的事情,但是要使用罗马数字。我们从开始I并遵循相同的规则(我们将数字计数规则应用于字符,因此我们将其读IVXone one, one five, one ten而不是one four, one ten或某种其他方式):

I           "one"
II          "one one"
III         "two ones" = "II" + "I"
IIII        "three ones" = "III" + "I"
IVI         "four ones" = "IV" + "I"
IIIVII      "one one, one five, one one"
IIIIIVIII   "three ones, one five, two ones" = ("III" + "I") + ("I" + "V") + ("II" + "I")

给定一个正整数N,则:

  • 输出N此序列的第一个数字(可以使用任何合理的分隔符,["I", "II", "III", ...]
  • N此序列的输出项(可以为0索引)。

记住要使代码尽可能短,因为这是挑战!

编辑:我相信,总是存在一种将整数表示为罗马数字的标准/首选方式(例如95-> XCV而不是VC)。我在网上发现了几个罗马数字转换器,这证实了我的观点。如有疑问,请使用在线转换器,因为列出所有可能的边缘情况和书写罗马数字的特定规则并不是这一挑战的重点。

EDIT2:@PeterTaylor和@GregMartin指出,只有数小于或等于5出现的顺序,所以你不必对罗马数字的不确定性的担心(数字1- 8IIIIIIIVVVIVII,和VIII


每个整数没有唯一的罗马数字表达式。可能需要表达哪些数字,以及这些数字的哪些表达形式有效?
彼得·泰勒

您的意思是“每个整数都没有唯一的罗马数字表达式”?喜欢4/ IV/ IIII吗?或95/ XCV/ VC?不一定总是有一种独特的方式来表达整数,但是我敢肯定,总会有一种首选的(标准)方式-如果我写错了,请更正我。
shooqie '16

1
我们的罗马数字要走多远?
Maltysen '16

是的,这两种情况。在第二种情况下,我认为这是一个非常可取的问题。
彼得·泰勒

9
@shooqie如果这些细节没有弄清楚,您将如何比较答案?如果还有一些边缘情况需要解释,那么实际得分将变得毫无意义,因为它们可能会比您想出的任何高尔夫技巧都产生更大的影响。
Martin Ender

Answers:


17

Perl,49个字节

包括+1 -p

在STDIN上使用基于0的索引运行

ecce.pl <<< 14

ecce.pl

#!/usr/bin/perl -p
s,(.)\1*,$&/$1%182 .$1,eg for($_=/$/)x$`;y;19;IV

魔术公式是如此神奇。

通常,我将($_=//)x$'循环控制的使用时间缩短了一个字节,但是在此站点上的得分则让分差为2,因此最终增加了1个字节。在较早的Perls上,您可以在之前删除空格for。某些版本的perl会强制您添加final ;以关闭音译。但是上面给出的是可以在我的系统上运行的代码。

说明

从解决方案到代码的反向工作:

我们需要的字符串转换:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

每次替换均以重复的字符结尾。我将使用正则表达式得到一个相同字符的序列/(.)\1*/,因此可以通过追加来完成$1。之前的部分在->$&。因此,我仍然需要:

I     -> I
II    -> II
III   -> III
IIII  -> IV
IIIII -> V

V     -> I
VV    -> II

I1and Vas 9:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

9     -> 1
99    -> 11

通过将前面的部分除以->重复的数字,将得到:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

1     -> 1
11    -> 11

因此,现在重复的原始内容V已不再是一个例外。所以我想要一个使这种情况发生的表达式:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

这可以通过简单的模182来完成:

1     % 182 = 1
11    % 182 = 11
111   % 182 = 111
1111  % 182 = 19
11111 % 182 = 9

(尽管这里不需要,这甚至可以IIIIII解决VI

所有剩下的正在初始化工作变量1为指数0,重复这种转变在循环中,并在年底更换1I并且9通过V

19并且182是此简单公式适用的唯一参数组合。


2
这是天才!:)
林恩

10

Mathematica,113 90 83字节

感谢Martin Ender提出的建议,将长度减少了25%以上!

展示Mathematica中的高级命令。

Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&

一个纯函数,采用参数N并将此(0索引)序列的第N个元素输出为字符列表。散开一点:

Nest[
  Flatten[
    Characters @ {RomanNumeral@#,#2}& @@@
      Reverse @@@ Tally /@ Split@ #
    ]& ,
  {"I"}, #]&

外部Nest迭代从{"I"}N次开始的中间四行函数。第4行将输入罗马数字的字符列表拆分为类似字符的游程,使用计数每个游程Tally,并将计数放在它们要计数的字符之前。第3行将计数呈现为罗马数字,然后将这些罗马数字分成字符列表。该Flatten命令将整个列表缩减为一维列表。

这是初始版本:

Nest[
  "" <> Flatten[{RomanNumeral@#[[1]], #[[2]]} & /@
    (Reverse@#[[1]] & /@ 
      Tally /@
        Split@Characters@#)] &,
  "I", #] &

3
Grrr Mathematica;)
Beta Decay's

如果使用@@@代替,则/@可以使用##2代替#[[1]]#[[2]]。另外,字符列表是可接受的字符串类型,因此您可以使用它们,并避免使用Characters@
马丁·恩德

@MartinEnder阿哈,我知道一定有一个类似@@@的捷径!至于可接受的字符串类型的字符列表(我同意这会缩短代码):您是否可以在此站点上发帖介绍社区标准?
格雷格·马丁


1
还有一些节省:Characters自动线程化,因此您可以使用@Reverse@#&当然与plain相同Reverse,在这种情况下,您也不需要那些括号。Flatten如果需要添加括号以使其起作用,则前缀表示法(对于)不会保存任何内容。结合所有这些条件:Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&
Martin Ender

8

CJam(33 30字节)

"I"{e`{(4md1$^'I*\'V*@}%e_}ri*

在线演示

实现正确性的关键在于以下定理:

如果是第一代I,则游程长度不会大于5

引理:如果是第一代,则I不会包含任何字符串VVV。证明是矛盾的。假设存在第一个世代包含nn第一个索引VVV。如果该操作VVV失败了,(a)V VV那么上一代的转换就很糟糕:应该是(a+5)V。因此VV V(d),上一代人必须与之VVVVV矛盾n

现在,假设第一个世代包含mm第一个索引...IIIIII...。请注意,不可能有比其他数字IV在字符串,因为没有上一代已经有一个九岁的运行I秒或9 V秒。最多四个Is来自I前一个字符串中的s 游程,因此前一个字符串的相应部分必须为...IIIVV...给出... IIII IIV ...。由于VVin代m-1不是来自VVVVV(参见引理),因此第二个V必须是数字的游程长度I,因此在in代中m-1我们有...IIIVVI...。而且因为我们希望初期Is到给予IIII,而不是IVIVI,它以字符串开头或V。开头。

如果我们有(...V)?IIIVVI...一代人m-1,我们会有什么一代人m-2?我们已经观察到VVgen了。m-1必须解析为(a)V V(I)

假设我们认为a=2:尽管领导可能是其中的一部分,但(...V)?I IIV VI...实际上一定是...VI IIV VI...这样; 因此,在上一代中,我们拥有或。无论哪种方式,我们都会遇到麻烦:第二个必须是游程长度,但随后需要具有相同数字的后续(游程长度,数字)对。VIV(...V)? IIII VV IIIII...(...V)? IIIII VV IIIIIVVIIIIIV...VI IIII...

因此它必须是a=1(...V)?II IV VI...。由于代m是先用六个运行I的时候,那些必须是(...V)? II IV VI...,这样产生m-2(...V)? I V IIIII......VIVIIIII...这是不可能的:但是,我们选择解释第二个V,最后得到两个具有相同数字的连续(游程长度,数字)对。

因此,生成m-2必须被^IVIIIII...解析为^IV IIII I(V)...^IV III II(V)...。这些分别产生m-3^V III V ...^V II VV...

但是,如果我们查看以第一个以开头的字符串开头的字符串的开头,则会V得到一个循环:

    VI IV I...
    IV III IV ...
    II IV IVI ...
    IIII IV II IV ...

所以没有一代以VIIIV或开头VIIVV。我们必须得出结论,没有这样的结论m

解剖

"I"          e# Initial generation
{            e# Loop...
  e`         e#   Run-length encode
  {          e#   Foreach [run-length char] pair...
    (        e#     Extract the run-length r
    4md1$^   e#     Get the number of Vs and the number of Is
             e#     The number of Vs is r/4 ; the number of Is is (r%4)^(r/4)
    'I*\'V*@ e#     Repeat strings the appropriate number of times and reorder
  }%
  e_         e#  Flatten to a simple string
}ri*         e# ... n times, where n is taken from stdin

6

Python 3,195个字节

罗马数字上浪费了很多字节,因此可能需要打高尔夫球。

感谢@ El'endiaStarman,@ Sherlock9和@Shooqie

import re
def f(x,r=""):
 for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*a
 return r
s="I"
for i in[0]*int(input()):print(s);s=re.sub(r'(.)\1*',lambda m:f(len(m.group()))+m.group()[0],s)

伊迪恩!


您可以省略方括号:for v,i in(5,"V"),(4,"IV"),(1,"I")
shooqie '16

@shooqie我不知道您可以做到这一点:D
Beta Decay

for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*a保存一个字节。
Sherlock9年

@βετѧΛєҫαγ:另外,您似乎并没有使用i(如中所述for i in range(...))。我试着摸索,exec但是1在'sub'方法中转义的这似乎使代码弄乱了,我一直找不到解决方法。
shooqie '16

@shooqie我通过摆脱掉它来缩短了它的时间range
Beta Decay

4

R,110个 107字节

as.roman与结合rle使此操作变得容易。界定滥用行为和内置的cat行为<<-可以节省一些字节。

x="I"
replicate(scan(),{r=rle(strsplit(x,"")[[1]])
x<<-paste(rbind(paste(as.roman(r$l)),r$v),collapse="")})

从控制台获取N。输出前2到N个序列项(我认为这在规范范围内...)

 [1] "II"                                                                                                                                                                                                                                     
 [2] "III"                                                                                                                                                                                                                                    
 [3] "IIII"                                                                                                                                                                                                                                   
 [4] "IVI"                                                                                                                                                                                                                                    
 [5] "IIIVII"                                                                                                                                                                                                                                 
 [6] "IIIIIVIII"                                                                                                                                                                                                                              
 [7] "VIIVIIII"                                                                                                                                                                                                                               
 [8] "IVIIIIVIVI"                                                                                                                                                                                                                             
 [9] "IIIVIVIIVIIIVII"                                                                                                                                                                                                                        
[10] "IIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                                               
[11] "VIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                                                
[12] "IVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                                                          
[13] "IIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                                                                   
[14] "IIIIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                      
[15] "VIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                 
[16] "IVIIIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                         
[17] "IIIVIVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                            
[18] "IIIIIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                           
[19] "VIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                              
[20] "IVIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                    
[21] "IIIVIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                             
[22] "IIIIIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIIVIVIIVIIIIIVVIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                      
[23] "VIIVIIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVVIIVIIIVIIIIVVIIIVIIIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                   
[24] "IVIIIIVVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIIVIIIIVIIIIIVIVIIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                             
[25] "IIIVIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIVIIVVIIVIIIVIIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"

1

JavaScript(ES6),107

递归函数返回第N个项,从0开始

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

测试

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

function update() {
  O.textContent=f(I.value)
}

update()
<input id=I value=25 type=number oninput='update()'><pre id=O></pre>


1

Perl 6,62个字节

{("I",{S:g/(.)$0*/{<I II III IV V>[$/.chars-1]~$0}/}...*)[$_]}

接受从零开始的索引的匿名函数。

利用了不需要罗马数字大于5的事实,因为可能出现的唯一重复数字组是:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

在线尝试

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.