Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Challenges

Comments on The 50 substrings that validate any string of Roman numerals

Parent

The 50 substrings that validate any string of Roman numerals

+10
−0

Given a string of Roman numerals, decide whether it forms a valid Roman number. If not, output the substring that proves this, from the list of 50 strings described below.

Relevant fact

This challenge is based around the following fact:

A string of Roman numerals is a valid Roman number if and only if it contains none of the following 50 strings as a substring:

"CCCC", "CCD", "CCM", "CDC", "CMC", "CMD", "CMM", "DCD", "DCM", "DD", "DM", "IC", "ID", "IIII", "IIV", "IIX", "IL", "IM", "IVI", "IXC", "IXI", "IXL", "IXV", "IXX", "LC", "LD", "LL", "LM", "LXC", "LXL", "MMMM", "VC", "VD", "VIV", "VIX", "VL", "VM", "VV", "VX", "XCC", "XCD", "XCL", "XCM", "XCX", "XD", "XLX", "XM", "XXC", "XXL", "XXXX"

This works for any length string, if a valid Roman number is defined as follows:

Valid Roman numbers[1]

  • Each numeral appears no more than 3 times consecutively.
  • Each of V (5), L (50), and D (500) appears no more than once consecutively.
  • A Roman number is constructed by concatenating the strings representing its thousands, hundreds, tens, and units components.
Decimal Thousands Hundreds Tens Units
1 M C X I
2 MM CC XX II
3 MMM CCC XXX III
4 CD XL IV
5 D L V
6 DC LX VI
7 DCC LXX VII
8 DCCC LXXX VIII
9 CM XC IX

So, for example, 2345 would be represented as the concatenation of MM (for 2000), CCC (for 300), XL (for 40), and V (for 5), or MMCCCXLV.

This defines a unique correct representation for each number from 1 to 3999 (4000 and above are not representable without breaking the first two rules). The 50 substrings method described above will identify each of these 3999 strings as valid, and all other strings of Roman numerals as invalid.

Input

  • A string containing only Roman numerals (I, V, X, L, C, D, M).
  • The string will have length at least 1.
  • The string will have length at most 15 (this is the length of the longest valid string of Roman numerals).
  • You may choose to take input in lower case instead, provided that you also use lower case in your output for an input that is not a valid Roman number.

Output

  • If the input is a valid Roman number, output a consistent value indicating this.
    • Consistent means that the value must be the same for all valid Roman numbers.
    • The output for a valid Roman number must not be one of the strings from the list of 50.
    • Since the consistent value can be anything (and specifically does not need to contain Roman numerals), there is no requirement for it to be upper or lower case.
  • If the input is not a valid Roman number, output exactly 1 string from the list of 50.
    • The output in this case must be a substring of the input.
    • If the input has 2 or more of the strings from the list of 50 as substrings, you may choose any 1 of them to be the output, but you must choose only 1 of them (you must not output 2 or more).
    • If you chose to take input in lower case, then this output string must also be in lower case.

Examples

A valid Roman number

The input MCMXCVI is the unique correct representation of 1996. It contains none of the 50 strings.

A string that is not a valid Roman number

Although the input MMXDIII might be suspected of representing 2493, it is not the unique correct representation of this number (which is MMCDXCIII). Note that it has XD as a substring, identifying it as invalid. The only correct output is therefore XD.

An invalid string with more than 1 potential output

The input MMCCMDXXV has 2 substrings that make it invalid, so either CCM or CMD would be correct outputs. It would not be correct to output both of these, or to output their overlap CCMD, as this is not one of the 50 strings.

Test cases

Test cases are in the format INPUT : VALID, OUTPUTS. Note that only one of the valid outputs can be chosen - outputting 2 or more is incorrect.

The output "VALID" is just an example - for an input that is a valid Roman number you may choose to output any consistent value distinct from the 50 strings.

Upper case test cases

These reflect the case used in the rest of the challenge wording, although there is no requirement to use upper case for this challenge.

I : VALID
V : VALID
X : VALID
L : VALID
C : VALID
D : VALID
M : VALID
II : VALID
VV : VV
XX : VALID
LL : LL
CC : VALID
DD : DD
MM : VALID
III : VALID
VII : VALID
IVI : IVI
IIV : IIV
CCI : VALID
CCV : VALID
CCX : VALID
CCL : VALID
CCC : VALID
CCD : CCD
CCM : CCM
IIII : IIII
MLDI : LD
MXXC : XXC
DCIIX : IIX
MCXXXX : XXXX
MCCCCXVI : CCCC
MMLXCVII : LXC
MMMCMXCIX : VALID
MMMDCCCLXXXVIII : VALID
MMCCCXLV : VALID
MCMXCVI : VALID
MMXDIII : XD
MMCDXCIII : VALID
MMCCMDXXV : CCM, CMD
XXX : VALID
CLLX : LL
DXXDMMV : DM, XD
CCDDDIMDD : DD, IM, CCD
VLCXIVXMCVXLC : VX, VL, LC, XM
DVLIILVCXVXVMLI : VX, VL, IL, VM, VC
VVDLMIVILXXDX : VV, VD, IL, XD, LM, IVI
DMXXCMILVCMLLMV : DM, IL, LL, VC, LM, XXC, XCM
CMXDVLCCDDLXLXC : DD, VL, LC, XD, XLX, LXC, CCD, LXL
XDIXCLLMVVLCMCM : VV, VL, LC, XD, LL, LM, IXC, CMC, XCL
IIXXCDVVLMILVDD : DD, VV, VL, VD, IL, LM, XXC, IXX, IIX, XCD
DDMIIXXCMCCDCMM : DD, DM, CMC, CMM, XXC, IXX, DCM, CDC, XCM, CCD, IIX

Lower case test cases

These are the same test cases in lower case, in case you can benefit from taking lower case input.

Note that if you take lower case input then you must also give lower case output where it is one of the 50 strings.

i : valid
v : valid
x : valid
l : valid
c : valid
d : valid
m : valid
ii : valid
vv : vv
xx : valid
ll : ll
cc : valid
dd : dd
mm : valid
iii : valid
vii : valid
ivi : ivi
iiv : iiv
cci : valid
ccv : valid
ccx : valid
ccl : valid
ccc : valid
ccd : ccd
ccm : ccm
iiii : iiii
mldi : ld
mxxc : xxc
dciix : iix
mcxxxx : xxxx
mccccxvi : cccc
mmlxcvii : lxc
mmmcmxcix : valid
mmmdccclxxxviii : valid
mmcccxlv : valid
mcmxcvi : valid
mmxdiii : xd
mmcdxciii : valid
mmccmdxxv : ccm, cmd
xxx : valid
cllx : ll
dxxdmmv : dm, xd
ccdddimdd : dd, im, ccd
vlcxivxmcvxlc : vx, vl, lc, xm
dvliilvcxvxvmli : vx, vl, il, vm, vc
vvdlmivilxxdx : vv, vd, il, xd, lm, ivi
dmxxcmilvcmllmv : dm, il, ll, vc, lm, xxc, xcm
cmxdvlccddlxlxc : dd, vl, lc, xd, xlx, lxc, ccd, lxl
xdixcllmvvlcmcm : vv, vl, lc, xd, ll, lm, ixc, cmc, xcl
iixxcdvvlmilvdd : dd, vv, vl, vd, il, lm, xxc, ixx, iix, xcd
ddmiixxcmccdcmm : dd, dm, cmc, cmm, xxc, ixx, dcm, cdc, xcm, ccd, iix

Scoring

This is a code golf challenge. Your score is the number of bytes in your code. Lowest score for each language wins.

Explanations are optional, but I'm more likely to upvote answers that have one.


  1. This is a common modern set of rules, described as Standard form on Wikipedia. It does not reflect all usages during history, but will be the basis of this challenge, since otherwise the 50 substrings approach does not work. ↩︎

History

1 comment thread

Casing (2 comments)
Post
+2
−0

Perl, 119 bytes

Read a single Roman numeral on stdin (optionally newline-terminated). Outputs nothing unless one of the 50 strings is found, in which case it is printed (without trailing newline):

perl -pe'($_)=/([CIMX])\1{3}|C[CM][DM]|C[DM]C|I[IX][VX]|I[VX]I|VI?[VX]|XC[CLX]|XLX|[DX]C?[DM]|[ILV][CDLM]|[ILX]X[CL]/g'

Minimising a regex is nontrivial but will probably be the bulk of any solution. I expect it is possible to shrink it even more than this attempt.

  • -p - load each line of input as $_, manipulate, then print
  • -e - program follows
  • /.../g - return list of all matches
  • ($_) = ... - store first match in $_ (if no matches, assigns empty string)

To read a newline-separated list of numerals and to print "VALID" instead of nothing increases code to 126 bytes:

perl -ple'$_=/([CIMX])\1{3}|C[CM][DM]|C[DM]C|I[IX][VX]|I[VX]I|VI?[VX]|XC[CLX]|XLX|[DX]C?[DM]|[ILV][CDLM]|[ILX]X[CL]/?$&:VALID'
  • $_ = /.../ ? $& : VALID - ternary assignment to $_ - if a match is found, assign its value ($&), otherwise assign bareword VALID

Try it online!

History

1 comment thread

Input method (4 comments)
Input method
trichoplax‭ wrote 7 months ago

Takes newline-separated list of Roman numerals as input

Does this mean you take multiple test cases and give multiple outputs, or you take a single test case spread over multiple lines?

The input section specifies:

A string containing only Roman numerals (I, V, X, L, C, D, M).

This is intended to mean just a single input, with no newlines, such as MCMXCVI.

Let me know if there's a way the challenge wording could be clarified.

jhnc‭ wrote 7 months ago · edited 7 months ago

I mean my code will handle one or more test cases, each separated by a newline. If only a single test case is entered the trailing newline is optional.

For example, on linux, printf MCCCCXVI | perl ... or echo MMMDCCCLXXXVIII | perl ... or printf '%s\n' IIV DCIIX MMXDIII | perl ... should all work. output for each test case will be terminated by a newline

To handle precisely one testcase, and not output trailing newline, would actually make the code 1 byte shorter as the l option can be elided

jhnc‭ wrote 7 months ago

I've added a link to a slightly modified version for testing

trichoplax‭ wrote 7 months ago

Thanks for explaining. If 1 byte shorter is sufficient for one test case at a time, that should be your score. The convenience of also having a longer version that covers all the test cases at once shouldn't cost you in score. Feel free to include both in your answer, but take the credit for the short version.