# Find Roman numerals up to 100 that do not contain “I"

The question is from Elementary Introduction to the Wolfram Language, section 28 Tests and Conditionals: Find Roman numerals up to 100 that do not contain “I”.

What am I doing wrong that the following code is not returning the desired output?

Select[RomanNumeral[Range[100]], MemberQ[#, "I"]&]


I can't quite figure out where I am going wrong.

Thanks!

• MemberQ is for lists. So, you could split the string into characters first (and use Not). Or you could just use StringFreeQ on the roman numeral strings. Commented Jun 7, 2023 at 16:40

The Roman numerals are strings, not lists (or another expression). So MemberQ will return False.

Select[RomanNumeral[Range[100]],
! MemberQ[Characters@#, "I"] &]


Or:

Select[RomanNumeral[Range[100]], StringFreeQ["I"]]


Also:

RomanNumeral[Range[5, 100, 5]]


• Roman zero N gets no respect. 😉 Commented Jun 9, 2023 at 16:04
• @chux-ReinstateMonica Mma respects it: RomanNumeral[Range[0, 100, 5]]. It's unclear whether nulla was considered a number, or even whether N was used by the Romans since, according to the Wiki article, "the earliest attested instances are medieval." Commented Jun 9, 2023 at 16:52
• Much of the rules about Roman numbers achieved their greater uniformity (as in this good answer) long after Roman times. Else XXXX, (and the like) should be on the list too. Commented Jun 9, 2023 at 17:51

I include some variations.

rn100 = RomanNumeral@Range@100;

Cases[rn100, _?(StringFreeQ["I"])]

DeleteCases[rn100, _?(StringContainsQ["I"])]

DeleteCases[rn100, _?(StringMatchQ[___ ~~ "I" ~~ ___])]

Complement[rn100, Cases[rn100, _?(StringMatchQ[___ ~~ "I" ~~ ___])]] //
SortBy[#, FromRomanNumeral] &

Pick[rn100, StringMatchQ["*I*"] /@ rn100, False]

Pick[rn100, StringMatchQ[Except["I"] ..]@rn100]

Select[rn100, # == StringDelete[#, "I"] &]

Select[rn100, StringPosition[#, "I"] == {} &]


Result:

{"V", "X", "XV", "XX", "XXV", "XXX", "XXXV", "XL", "XLV", "L", "LV",
"LX", "LXV", "LXX", "LXXV", "LXXX", "LXXXV", "XC", "XCV", "C"}

• Now that's just flexing. Commented Jun 9, 2023 at 9:16

Another way using GroupBy and Extract:

rn100 = RomanNumeral@Range@100;

Extract[GroupBy[rn100, FreeQ[Characters[#], "I"] &], Key[True]]


Or using GroupBy and Lookup:

Lookup[GroupBy[rn100, FreeQ[Characters[#], "I"] &], True]


Or using ReplaceAll:

rn100 /. x_?StringQ /; ! StringFreeQ[x, "I"] :> Nothing


Edit Thanks to the comment by @eldo, there's a shorter version using GroupBy:

GroupBy[rn100, FreeQ[Characters[#], "I"] &][True]

• +1 - GroupBy[rn100, FreeQ[Characters[#], "I"] &][True]  would suffice
– eldo
Commented Apr 3 at 0:07
• Cheers, @eldo! I update the answer :) Commented Apr 3 at 0:10

Or use regex.

"Now you have two problems"

Range[100] // RomanNumeral // Select[StringMatchQ[RegularExpression["[^I]*"]]]


https://xkcd.com/1171/ Perl Problems

list = RomanNumeral[Range @ 10]


{"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"}

Pick[list, StringFreeQ["I"] /@ list]

GroupBy[list, StringFreeQ @ "I"][True]

Replace[list, _?(StringContainsQ["I"]) :> Nothing, {1}]
`

All return

{"V", "X"}