# Straight pen strokes for Prime Numbers

### Challenge

You are supposed to output the series I recently designed which goes as follows which are pen stroke counts of ascending prime numbers:

2, 3, 2, 4, 3, 5, 6, 5, 7, 7, 7, 10, 4, 6, 7, 4, 4, 4, 7, 6, 8...


### Example

This is an illustration of how this series is formed, first, it takes a prime number from in sequence form, so it takes the first prime number 2. It converts it to the Roman numeral of 2, which is II, here pen stroke is a straight long line, in this case, it is two so the first element in this series is 2.

### Dictionary

It will really be confusing to explain the pen stroke for each letter, and we know all Roman numerals contain characters I, V, X, L, C, D, M only, here is already shown pen stroke value of each letter

0  C
1  I, L, D
2  V, X
3  [None]
4  M


For example MMMMMMMCMXIX is the Roman numeral 7919 so you compare it with the above dictionary M has 4 pen strokes and so on, they add to 37 pen strokes.

### Ambiguities

It can be queried why M is not assigned 2 strokes, and L is not assigned 2 strokes; it is because they are not written this way in numeral numbers. As M and L are written:

In standard Roman numerals, M makes 4 pen strokes and L as 1 because another line of L is too small to be considered a pen stroke.

Write the shortest code in the number of bytes that takes an input number, and outputs as many elements from the input as possible.

### Test Cases

5 => 2, 3, 2, 4, 3
10 => 2, 3, 2, 4, 3, 5, 6, 5, 7, 7
15 => 2, 3, 2, 4, 3, 5, 6, 5, 7, 7, 7, 10, 4, 6, 7


Do not forget that it is the implementation of pen stroke counts of Roman numerals of prime numbers in ascending order only!

• Looks like a multipart challenge with unrelated sub-tasks. Unless there's a good reason I'm missing, you should probably remove the prime constraint. Apr 23, 2023 at 17:51
• I'd recommend adding the sequence tag. This would allow a more flexible output format. Apr 23, 2023 at 17:58
• I am not an experienced member yet, but I would still insist that it is a related subtask, the question relates pen strokes, primality testing and Roman numerals and they all function together, if I remove the primality option, it would further get easy, the task remains hard. It is the same as how Sophie Germain primes and Safe primes are used in Sophie Safe primes. Just insisting :') Apr 23, 2023 at 17:59
• Am I missing something? MMMMMMMCMXIX has 37 pen strokes, not 33. (M:4 x 8 + C:0 x 1 + X:2 x 2 + I:1 = 32 + 0 + 4 + 1 = 37) Apr 23, 2023 at 21:13
• so e.g. 99000 would be 99 Ms?
– att
Apr 24, 2023 at 22:20

# Vyxal,  15  14 bytes

-1 thanks to lyxal (vectorisation).

ʁǎøṘC»ṫN»$%5%Ṡ  Try it Online! ### How? ʁǎøṘC»ṫN»$%5%∑ - input a non-negative integer, N
ʁ               - range -> [0..N-1]
ǎ              - ith prime -> [2,3,5,...p(N)]
øṘ           - to roman numerals   :  I   V   X   L   C   D   M
C          - cast to ordinals      73  86  88  76  67  68  77
»ṫN»      - 39602
\$     - swap
%    - modulo                36  42   2   6   5  26  24
5%  - modulo five            1   2   2   1   0   1   4
Ṡ - sums


# Vyxal, 19 18 bytes

ʀǎƛøṘkṘvḟ»øṪK»fvi∑


Try it Online!

ʀǎƛøṘkṘvḟ»øṪK»fvi∑
ʀǎƛ                 # map over each of the first n primes:
øṘ               #   convert to roman numerals
kṘvḟ           #   index of each character in "IVXLCDM"
»øṪK»f     #   digits of compressed integer 1221014
vi   #   index each into digit list
∑  #   sum


# Factor + math.primes math.unicode roman, 63 bytes

[ nprimes [ >roman [ "c--ildvx----m"index 3 /i ] map Σ ] map ]


Try it online!

[                            ! start quotation (anonymous function)
nprimes                  ! get a list of the first number of primes indicated by input
[                        ! start map
>roman               ! convert current prime to roman numerals
[                    ! start map
"c--ildvx----m"  ! push string to stack
index            ! find the index of the current letter in the string
3 /i             ! integer divide by 3
] map                ! map over each letter in the roman numerals of current prime
Σ                    ! take sum of results of the letters
] map                    ! map over the first n primes
]                            ! end quotation


# 05AB1E, 14 bytes

Åpε.XÇŽœ
s%5%O


Port of JonathanAllan's Vyxal answer, so make sure to upvote him as well!

Try it online.

Outputting the infinite sequence without input would be 14 bytes as well:

Žœ
∞<Ø.X€Ç%5%O


Try it online.

Explanation:

Åp               # Get a list of the first (implicit) input amount of primes
ε              # Map over each prime number:
.X            #  Convert it to a Roman number string
Ç           #  Convert this string to a list of its codepoint integers
Žœ\n       #  Push compressed integer 39602
s      #  Swap so the list of lists of codepoint integers is at the top
%     #  Modulo the 39602 by each of these codepoints
5%   #  Modulo-5 that
O  #  Take the sum of each inner list
# (after which the resulting list is output implicitly)


See this 05AB1E tip of mine (section How to compress large integers?) to understand why Žœ\n is 39602.

# Excel, 142 139 bytes

=LET(
a,SEQUENCE(99),
b,TOROW(a),
MMULT(
LOOKUP(
MID(ROMAN(TAKE(FILTER(a,MMULT(N(MOD(a,b)=0),a^0)=2),A1)),b,1),
{"","D","M","V"},
{0,1,4,2}
),
a^0
)
)


Input in cell A1. The static 99 within the part SEQUENCE(99) has been arbitrarily chosen and will generate a valid output for A1<26.

# Wolfram Language(Mathematica), 127 101 bytes

Saved 26 bytes thanks to @att's comment.

Golfed version. Try it online!

f=Tr[<|"C"->0,"I"->1,"L"->1,"D"->1,"V"->2,"X"->2,"M"->4|>/@Characters@RomanNumeral@Prime@#]&~Array~#&


Ungolfed versrion. Try it online!

strokeCounts = <| "C" -> 0, "I" -> 1, "L" -> 1, "D" -> 1, "V" -> 2, "X" -> 2, "M" -> 4 |>;

penStrokeCount[n_] := Module[{romanNumeral, strokes},
romanNumeral = IntegerString[Prime[n], "Roman"];
strokes = Total[Lookup[strokeCounts, Characters[romanNumeral]]];
strokes
]

primePenStrokes[n_] := Table[penStrokeCount[i], {i, 1, n}];

(* example usage *)
primePenStrokes[15]//Print (* outputs {2, 3, 2, 4, 3, 5, 6, 5, 7, 7, 7, 10, 4, 6, 7} *)
primePenStrokes[10]//Print (* outputs {2, 3, 2, 4, 3, 5, 6, 5, 7, 7} *)
primePenStrokes[5]//Print (* outputs {2, 3, 2, 4, 3} *)

• Convert this to an anonymous function; infix Table; the lower bound of Table and other iterators defaults to 1 (so can be omitted here), but Array is shorter anyways; prefix Tr; Lookup[<|...|>,list] -> <|...|>/@list; and finally the built-in roman conversion does interesting things for input ≥4000, which invalidates this answer.
– att
Apr 24, 2023 at 0:59
• Actually, I'll ask what's expected for primes ≥4000, since the question doesn't explicitly define what's expected there
– att
Apr 24, 2023 at 1:10
• @att Thanks for your comment! But, how to correct it? Apr 24, 2023 at 3:20
• In case there is no problem, RomanNumeral is shorter than IntegerString[...,"Roman"]
– att
Apr 24, 2023 at 8:31
• @att I have corrected it. Thank you very much :-) Apr 24, 2023 at 8:51

# JavaScript (ES6), 155 bytes

Full answer with all the irrelevant stuff.

f=(k,n=1)=>k?(g=d=>n%d--?g(d):d)(n++)?f(k,n):["2345545673"[n%10]-(g=d=>n/d%10%9<4)(10)-g(100)+11%~(q=-~n/10%5)*2+(q-4?4*!q:6)+(n/1e3+.1<<2),...f(k-1,n)]:[]


Try it online!

Here is the interesting part for easier testing: a function taking an integer and returning the number of straight pen strokes in its Roman numeral representation.

n=>"2345545673"[n%10]-(g=d=>n/d%10%9<4)(10)-g(100)+11%~(q=-~n/10%5)*2+(q-4?4*!q:6)+(n/1e3+.1<<2)


Try it online!

### Commented

n =>           // n = input
"2345545673"   // hard-coded number of straight strokes + 2 in I's
[n % 10] -     // and V's, which can be computed modulo 10
(              // g is a helper function processing L's and D's,
g = d =>     // which follow the same logic:
n / d % 10   //   divide n by the argument and reduce modulo 10
% 9          //   further reduce modulo 9
< 4          //   is the result less than 4?
)(10) -        // first call to g with d = 10
g(100) +       // 2nd call to g with d = 100
11 %           // the number of X's can be computed modulo 50
~(             // we first evaluate the generic expression:
q =          //   11 mod floor(q + 1)
-~n / 10 % 5 //   with q = ((n + 1) / 10) mod 5
) * 2 +        // and double the result to get the number of strokes
(              // we then apply two corrections:
q - 4 ?      //
4 * !q     //   +4 strokes if q = 0, i.e. n = 49 (mod 50)
:            //
6          //   +6 strokes if q = 4, i.e. n = 39 (mod 50)
) +            //
(              //
n / 1e3 + .1 // the number of M's is floor(n / 1000 + 1 / 10)
<< 2         // we multiply by 4 to get the number of strokes
)              //