10
$\begingroup$

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!

$\endgroup$
1
  • 3
    $\begingroup$ 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. $\endgroup$
    – lericr
    Commented Jun 7, 2023 at 16:40

5 Answers 5

13
$\begingroup$

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]]

Mathematica graphics

$\endgroup$
3
  • $\begingroup$ Roman zero N gets no respect. 😉 $\endgroup$ Commented Jun 9, 2023 at 16:04
  • $\begingroup$ @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." $\endgroup$
    – Michael E2
    Commented Jun 9, 2023 at 16:52
  • $\begingroup$ 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. $\endgroup$ Commented Jun 9, 2023 at 17:51
10
$\begingroup$

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"}

$\endgroup$
1
  • $\begingroup$ Now that's just flexing. $\endgroup$ Commented Jun 9, 2023 at 9:16
5
$\begingroup$

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]
$\endgroup$
2
  • 1
    $\begingroup$ +1 - GroupBy[rn100, FreeQ[Characters[#], "I"] &][True] would suffice $\endgroup$
    – eldo
    Commented Apr 3 at 0:07
  • $\begingroup$ Cheers, @eldo! I update the answer :) $\endgroup$ Commented Apr 3 at 0:10
3
$\begingroup$

Or use regex.

"Now you have two problems"

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

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

$\endgroup$
2
$\begingroup$
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"}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.