在罗马时,算不算罗马人?


20

背景

该挑战的灵感源于网站,网站发布了下图:

在此处输入图片说明

该图向我们展示了250以下的最长罗马数字表达式是188,需要9个数字来表示。

挑战

用于表达最罗马数字的标准符号如下:{ IVXLCDM},其中人物的数值是M= 1000,D= 500,C= 100,L= 50,X= 10,V= 5,I= 1。

在此挑战中,您的目标是给定正整数n,计算可通过串联n个标准符号组成的有效罗马数字表示形式的数量。

然后,您的程序必须输出该计算的结果!

输入:正整数n

输出:长度为n的有效罗马数字表达式的数量。

罗马数字表达规则

罗马数字最初只具有“加法”配对,这意味着数字始终按降序书写,并且所有数字的值之和就是数字的值。

后来,减法配对(为了减少大数字中的较小数字而使用)将较小的数字放置在较大的数字前面,从而缩短了罗马数字表达。减法对不能链接,如以下无效表达式中所示:IXL

以下是加减配对的现代规则。

  1. 在减法对中,只有I,X和C可以用作前导数字。
  2. 我只能在减法对中放在V或X之前。
  3. X只能在减法对中放在L或C之前。
  4. 在减法对中,C只能放在D或M之前。
  5. 除减法对之外,数字必须按降序排列(这意味着如果您删除每个减法对的前导数字,则数字将按降序排列)。
  6. 较小的面额不能等于或超过M,C和X。
  7. D,L和V只能出现一次。
  8. 仅M可以重复4次或更多次。

进一步说明

  • 我们将不会使用条形符号;相反,我们将简单地添加更多M来表示任何数字。

  • 这些是我们罗马数字遵循的唯一规则。这意味着诸如的奇数表达式IVI在我们的系统中也将被视为有效。

  • 还要记住,我们不计算长度为n的表达式的数目,因为有些数字具有多个表达式。相反,我们只计算有效表达式的数量。

测试用例

17

231

3105

我手动检查了以上内容,因此请确保仔细检查测试用例,并尽可能添加更多内容!

获奖标准

这是一个挑战赛,请尽情享受!我将只接受至少可处理1到9输入的解决方案。再多就是奖励!

编辑

根据评论者的要求,在下面或在此pastebin链接中,我算出n = 3 的105个连击

III IVI IXI IXV IXX VII XII XIV XIX XVI XXI XXV XXX XLI XLV XLX XCI XCV XCX XCL XCC XCC LII LIV LIX LVI LXI LXV LXX CII CIV CIX CVI CXI CXV CXX CXL CXC CLI CLV CLX CCI CCV CCX CCL CD CMI CMV CMX CML CMC CMD CMM DII DIV DIX DVI DXI DXV DXX DXL DXC DLI DLV DLX DCI DCV DCX DCL DCC MII MIV MIX MVI MXI MXV MXX MXV MXX MXL MXC MLI MLV MLX MCI MCV MCX MCL MCC MCD MCM MDI MDV MMX MML MMC MMD MMM

编辑2:

根据Jonathan Allan提供的代码,使用以下非高尔夫代码来检查结果。

编辑3:

对于此挑战中的所有错误,我深表歉意。下次我一定会做得更好!


评论不作进一步讨论;此对话已转移至聊天
Mego

Answers:


3

视网膜,111字节

~(`.+
*$(CM)CDXCXCXCXLIXIXIXIVII
.(.)
.+¶$$&$¶$$&$1$¶$$&$&¶L`.{0,$+}\b¶D`¶
¶$
¶.+¶$$&$¶$$&I¶L`[A-Z]{$+}\b¶D`¶.+

在线尝试!这是一个完全重写,因为我误解了规则1.意味着你只能使用每个消减的一个IXC。说明:脚本的第一部分将输入扩展为CM成对的字符串,然后是其他可能的减法对。每对是可选的,并且每对的第一个字符在该对内也是可选的。然后,第三阶段将对的列表扩展为Retina命令的列表,这些命令接受输入并创建三个副本,并选择该对中的第二个或两个字符,然后对结果进行修剪和重复数据消除。最后阶段然后追加代码以执行最终任务:首先扩展输入以可能添加最终I,然后滤除错误长度的结果,然后对结果进行重复数据删除,最后对结果进行计数。然后评估生成的Retina脚本。

注意:从理论上讲,从第4行的末尾可以保存15个字节,但这会使脚本太慢而无法在TIO上进行演示n=1


@JonathanAllan Ah,那么您要包括多个具有相同前导数字的减法对,这是错误的。
尼尔

2
@JonathanAllan新的重写,恰好是相同的字节数!
尼尔,

5

Python 2中177个168 162字节

import re,itertools as q
f=lambda n:sum(None!=re.match("^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$",(''.join(m)))for m in q.product('MDCLXVI',repeat=n))

在线尝试!

我很新,帮我打高尔夫球!这会检查实际的罗马数字,需要对正则表达式进行调整以解决诸如IVI

-9个字节感谢@Dead Possum!

-6个字节,感谢@ovs


是的,我认为在示例中n = 3的情况可能是错误的。我本来和93^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
Easton Bornemeier


1
@JonathanAllan我花了大约两天时间来研究Math stackexchange,以确保这些规则有意义。猜猜我做得还不够:(
Don Thousand

1
@RushabhMehta这是一个格式很好的挑战,而且编程很有趣,不要为罗马数字定义的细微差别感到遗憾。这是您的挑战,请根据需要指定。
换句话说

1
这似乎并没有给出3的正确答案,93而是105
Jo King

3

JavaScript(ES7),133个字节

编辑:固定为匹配Jonathan Allan的代码返回的结果,OP将该代码作为参考实现。


n=>[...Array(m=k=7**n)].reduce(s=>s+/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test((--k+m).toString(7).replace(/0[62]|2[34]|4[51]/g,s=>s[1])),0)

在线尝试!

怎么样?

ñ1个

[...Array(m = k = 7 ** n)].reduce(s => … (--k + m).toString(7) …, 0)

从现在开始,每个数字将被解释为罗马数字符号:

0一世1个中号2X3大号4C5d6V

2)我们将表格的所有有效减法对替换ABB

.replace(/0[62]|2[34]|4[51]/g, s => s[1]))  // in the code
.replace(/I[VX]|X[LC]|C[DM]/g, s => s[1]))  // with Roman symbols

例子:

  • XLIXIV 变成 LXV
  • XIIV变成XIV,留下一个I将使下一个测试失败
  • IC保持不变,这也将无效I位置保留

3)我们检查其余符号的顺序是否正确,并且出现的次数不超过允许的次数:

/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test(…)  // in the code
/^M*D?C{0,3}L?X{0,3}V?I{0,3}$/.test(…)  // with Roman symbols

天哪,我没想到用非深奥的语言用不到200个字节来完成这一任务!介意解释这是如何工作的?
Don Thousand

但是,我注意到这不适用于TIO上的* n *> 4,这有点不幸。
Don Thousand

@RushabhMehta我添加了一个非递归版本来测试更高的值。打完高尔夫球后,我将添加一个解释。
Arnauld

0

C, 150个 123字节

我没有足够仔细地阅读说明,所以这产生了标准罗马数字的数量(其中IVI不包括类似表达式)。由于我付出了很多努力,所以我认为我还是会分享。

#define F(X) for(X=10;X--;)
x[]={0,1,2,3,2,1,2,3,4,2};f(i,o,a,b,c){for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];return o;}

原始文件(150字节):

#define F(X) for(X=10;X--;)
i,o,a,b,c,x[]={0,1,2,3,2,1,2,3,4,2};main(){scanf("%i",&i);for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];printf("%i\n",o);}

1
只允许您发布有效的提交。
Okx

@CurtisBechtel我想您可以将解决方案保留在这里,但是我会尝试修改它以满足挑战的规则。
Don Thousand

1
我认为您可以删除F(X)for(X=10;X--;)
–Zacharý18年
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.