# Integer goes back and forth through time

Input:

An integer.

Output:

1. First convert the integer to it's equivalent Roman Numeral.
2. Then convert each capital letter of that Roman Numeral to their ASCII/UNICODE decimal value.
3. And output the sum of those.

Example:

1991 -> MCMXCI -> 77+67+77+88+67+73 -> 449
^ input                                ^ output


Challenge rules:

• Standard Roman Numeral rules are applied, so no alternative forms like IIII or VIIII instead of IV and IX.*
• The Macron lines above the Roman Numerals past 1,000 are ¯ (UNICODE nr. 175). So one line counts as +175 and two as +350.
• You are allowed to use any kind of input and output type, as long as it represents the integers.
• The test cases will be in the range of 1 - 2,147,483,647.

* Roman Numeral rules (quote from Wikipedia):

Numbers are formed by combining symbols and adding the values, so II is two (two ones) and XIII is thirteen (a ten and three ones). Because each numeral has a fixed value rather than representing multiples of ten, one hundred and so on, according to position, there is no need for "place keeping" zeros, as in numbers like 207 or 1066; those numbers are written as CCVII (two hundreds, a five and two ones) and MLXVI (a thousand, a fifty, a ten, a five and a one).

Symbols are placed from left to right in order of value, starting with the largest. However, in a few specific cases, to avoid four characters being repeated in succession (such as IIII or XXXX), subtractive notation is often used as follows:

• I placed before V or X indicates one less, so four is IV (one less than five) and nine is IX (one less than ten)
• X placed before L or C indicates ten less, so forty is XL (ten less than fifty) and ninety is XC (ten less than a hundred)
• C placed before D or M indicates a hundred less, so four hundred is CD (a hundred less than five hundred) and nine hundred is CM (a hundred less than a thousand)
For example, MCMIV is one thousand nine hundred and four, 1904 (M is a thousand, CM is nine hundred and IV is four).

Some examples of the modern use of Roman numerals include:
1954 as MCMLIV; 1990 as MCMXC; 2014 as MMXIV
SOURCE

General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
• Default Loopholes are forbidden.

Test cases:

100          ->   67
1            ->   73
4            ->   159
22           ->   322
5000         ->   261
2016         ->   401
1000000000   ->   427
1991         ->   449
9999         ->   800
1111111111   ->   2344
2147483647   ->   5362

• Related Aug 1, 2016 at 8:51
• @martin 9999 -> M(X)CMXCIX -> 77+263+67+77+88+67+73+88 -> 800 and 2147483647 -> ((MMCXLV)MMCDLXXX)MMMDCXLVII -> 427+427+417+438+426+436 + 252+252+242+243+251+263+263+263 + 77+77+77+68+67+88+76+86+73+73 -> 5362. So I've corrected the second, but the 9999 was correct. Aug 1, 2016 at 9:35
• The test case 2222222222 isn't in the given range. Also I agree with 5362.
– Neil
Aug 1, 2016 at 10:05
• The title kinda sounds like a Stack Overflow C question. Aug 1, 2016 at 12:02
• Is the word "fourth" in the title a pun? If not, it should be "forth". Aug 1, 2016 at 20:47

# Python 3, 281278273 269 bytes

My first attempt at codegolf, here we go. Tried to do it without looking at the linked question, so it's probably terrible :)

def f(n):d=len(str(n))-1;l=10**d;return 0if n<1else(n<l*4and[73,88,67,77,263,242,252,438,417,427][d]+f(n-l))or(l<=n//9and[161,155,144,340,505,494,690,855,844][d]+f(n-9*l))or(n<l*5and[159,164,135,338,514,485,688,864,835][d]+f(n-4*l))or[86,76,68][d%3]+(d//3*175)+f(n-5*l)


8 bytes smaller, thanks to Gábor Fekete

Ungolfed:

def f(n):
d = len(str(n)) - 1 # number of digits minus one
l = 10 ** d         # largest power of 10 that is not larger than parameter
if n == 0:
return 0
elif n < 4 * l: # starts with X, C, M, ...
return [
ord('I'),
ord('X'),
ord('C'),
ord('M'),
ord('X') + 175,
ord('C') + 175,
ord('M') + 175,
ord('X') + 350,
ord('C') + 350,
ord('M') + 350
][d] + f(n - l)
elif n // 9 * 10 >= 10 * l: # starts with IX, XC, ...
return [
ord('I') + ord('X'),
ord('X') + ord('C'),
ord('C') + ord('M'),
ord('M') + ord('X') + 175,
ord('X') + ord('C') + 350,
ord('C') + ord('M') + 350,
ord('M') + ord('X') + 525,
ord('X') + ord('C') + 700,
ord('C') + ord('M') + 700
][d] + f(n - 9*l)
elif n < 5 * l: # starts with IV, XL, CD, ...
return [
ord('I') + ord('V'),
ord('X') + ord('L'),
ord('C') + ord('D'),
ord('M') + ord('V') + 175,
ord('X') + ord('L') + 350,
ord('C') + ord('D') + 350,
ord('M') + ord('V') + 525,
ord('X') + ord('L') + 700,
ord('C') + ord('D') + 700
][d] + f(n - 4 * l)
else: # starts with V, L, D, ...
return [
ord('V'),
ord('L'),
ord('D'),
ord('V') + 175,
ord('L') + 175,
ord('D') + 175,
ord('V') + 350,
ord('L') + 350,
ord('D') + 350
][d] + f(n - 5 * l)

• You can golf some bytes by replacing return 0 if n==0 else with return 0if n<1else Aug 1, 2016 at 9:57
• Your golfed version has calls to f in it when the function's name is g. Aug 1, 2016 at 10:01
• Change n//9*10>=10*l to n//9>=l to save some more. Aug 1, 2016 at 10:03
• Fixed function name, I changed it to check if I golfed it correctly and forgot to change it back. Aug 1, 2016 at 10:08

# Mathematica, 181173166 151 bytes

## Golfed

(q=Select[ToCharacterCode@#,64<#<99&]&/@StringSplit[RomanNumeral[#],"_"];p=PadLeft;l=Length;Total[p[q,4]+p[{350,350*Mod[l@q,2],175,0}[[-l@q;;]],4],2])&


## Ungolfed

(
q = Select[
ToCharacterCode@#,
64<#<99&
]&/@StringSplit[RomanNumeral@#,"_"];
l=Length;
Total[
p[q,4]+
p[{350,350*Mod[l@q,2],175,0}[[-l@q;;]],4]
,2]
)&


Mathematica's RomanNumeral implementation gives (IX)CMXCIX for 9999, and so the program returns 971 for that number.

As written, a roman numeral of the type ((...))(...)... returns a nested list of the ASCII codes for the roman numerals of length 4, ((...))... returns a list of length 3, (...)... returns a list of length 2, and ... returns a list of length 1. The final line converts those rules into the appropriate number of macrons for each section of the list, adds those macrons in, and then sums the entire nested list to return the output.

• Welcome to PPCG! Aug 1, 2016 at 22:07
• @betseg Thank you! This was a fun first problem. Aug 1, 2016 at 22:21

# Ruby, 188 bytes

An adaptation based on my old Ruby answer for Roman numeral conversion. Try it online!

f=->x,i=0{k=0;(x<t=1e3)?"CM900D500CD400C100XC90L50XL40X10IX9V5IV4I1".gsub(/(\D+)(\d+)/){v=$2.to_i;s=x/v;x%=v;($1*s).bytes.map{|c|k+=c==73&&i>0?77+175*~-i:c+175*i}}:k=f[x/t,i+1]+f[x%t,i];k}


# Mathematica, 198 bytes

Tr[Tr@Flatten[ToCharacterCode/@#]+Length@#*Tr@#2&@@#&/@Partition[Join[SplitBy[Select[Characters@#/."\&"->1,MemberQ[Join["A"~CharacterRange~"Z",{1}],#]&],LetterQ]/. 1->175,{{0}}],2]]&@RomanNumeral@#&


Unfortunately, the builtin doesn't help here much, though I'm sure this can be golfed far more.

Note: Evaluates 9999 -> 971 as per here.

## Batch, 373 bytes

@echo off
set/an=%1,t=0,p=1
call:l 73 159 86 161
call:l 88 164 76 155
call:l 67 135 68 144
call:l 77 338 261 340
call:l 263 514 251 505
call:l 242 485 243 494
call:l 252 688 436 690
call:l 438 864 426 855
call:l 417 835 418 844
call:l 427 0 0 0
echo %t%
exit/b
:l


Works by translating each digit of the number according to a lookup table for the values 1, 4, 5 and 9. Uses M(V), M(X), (M(V)) and (M(X)). If you prefer (IV), (IX), ((IV)) and ((IX)) then use call:l 77 509 261 511 and call:l 252 859 436 861 respectively.

# R, 115 bytes

So... I'm posting my solution because I find the question pretty interesting. I did my best with R's capacities to deal with roman numbers without packages : you can only input numbers between 1 and 3899, as the as.roman's documentation explains.

That's why I cheated a bit by giving range between 1 to 11 14 in the for loop : it's the lenght of as.roman(3899)'s output (MMMDCCCXCIX).
In fact, according to this website, the longest roman number is MMDCCCLXXXVIII (14 characters), which corresponds to 2888.

Furthermore, you can't compute the length of the output of this function.

a=scan();v=0;for(i in 1:14){v=c(v,as.numeric(charToRaw(substring(as.character(as.roman(a)),1:14,1:14)[i])))};sum(v)


If anyone sees a solution to deal with the above problems, please feel free to comment.

• I don't understand why it thinks 3900 is ambiguous -- isn't that just MMMCM? I can get why it didn't do 4000 and up, though, since overline isn't the only convention for large numbers. Jul 7 at 14:47

# 05AB1E, 31 bytes

RƵêS£í.XÇεNĀi73¬Ć:Ny73Q-Ƶм*+]˜O


Explanation:

05AB1E does have a builtin to convert from/to Roman numbers. Unfortunately, $$\M=1000\$$ is the highest supported Roman digit, so it would convert something like 9999 to MMMMMMMMMCMXCIX. Because of this we'll split the input into parts at the 1000 separators, and convert each part separately. This results in the following code:

R                       # Reverse the (implicit) input-integer
Ƶê                     # Push compressed integer 334
S                    # Convert it to a list of digits: [3,3,4]
£                   # Split the reversed input into parts of that size
í                  # Reverse each individual part back
.X                # Convert it from an integer to a Roman number string
Ç               # Convert each string to a list of codepoint integer
ε              # Map over each list of codepoints:
NĀi           #  If the (0-based) map-index is NOT 0:
73         #   Push 73
¬        #   Push its first digit (without popping): 7
Ć       #   Append its own head: 77
:      #   Replace all 73 with 77 (replaces all "I" with "M")
y         #   Push the list of codepoints again
73Q      #   Check for each if it's equal to 73 ("I")
N    -     #   Subtract those checks from the (0-based) map-index
Ƶм*  #   Multiply each by the compressed integer 175
+ #   Add those to the list of codepoints (with 73 as 77)
]˜             # After the if-statement and map: flatten the list
O            # And sum this list of integers
# (after which it is output implicitly as result)


See this 05AB1E tip of mine (section How to compress large integers?) to understand why Ƶм is 175.

## JavaScript (ES6), 183 bytes

f=(n,a=0)=>n<4e3?[256077,230544,128068,102535,25667,23195,12876,10404,2648,2465,1366,1183,329].map((e,i)=>(d=e>>8,c=n/d|0,n-=c*d,r+=c*(e%256+a*-~(i&1))),r=0)|r:f(n/1e3,a+175)+f(n%1e3)


Note: not only prefers (IV) to M(V), but also prefers (VI) to (V)M; in fact it will only use M at the very start of the number.

# Python, 263 bytes

def g(m):x=0;r=[73,86,88,76,67,68,77,261,263,251,242,243,252,436,438,426,417,418,427,0,0];return sum([b%5%4*r[i+(i*1)]+((b==9)*(r[i+(i*1)]+r[(i+1)*2]))+((b==4)*(r[i+(i*1)]+r[i+1+(i*1)]))+((b in [5,6,7,8])*r[i+1+(i*1)])for i,b in enumerate(map(int,str(m)[::-1]))])

• Welcome to PPCG, nice first answer! Aug 2, 2016 at 11:07

# Python 3, 315 bytes

def p(n=int(input()),r=range):return sum([f*g for f,g in zip([abs(((n-4)%5)-1)]+[t for T in zip([((n+10**g)//(10**g*5))%2for g in r(10)],[(n%(10**g*5))//(10**g*4)+max((n%(10**g*5)%(10**g*4)+10**(g-1))//(10**g),0)for g in r(1,10)])for t in T],[73,86,88,76,67,68,77,261,263,251,242,243,252,436,438,426,417,418,427])])


Ungolfed version:

def p(n=int(input()),r=range):
return sum([f*g for f,g in zip(
[abs(((n-4)%5)-1)]+
[t for T in zip(
[((n+10**g)//(10**g*5))%2for g in r(10)],
[(n%(10**g*5))//(10**g*4)+max((n%(10**g*5)%(10**g*4)+10**(g-1))//(10**g),0)for g in r(1,10)]
)for t in T],
[73,86,88,76,67,68,77,261,263,251,242,243,252,436,438,426,417,418,427])])


Explanation: This version uses a different approach, it counts occurrences of roman numerals in the number.

[abs(((n-4)%5)-1)] is the number of Is in the roman numeral.

[((n+10**g)//(10**g*5))%2for g in r(10)] is the number of V,L,D,(V),(L),(D),((V)),((L)),((D))s in the number.

[(n%(10**g*5))//(10**g*4)+max((n%(10**g*5)%(10**g*4)+10**(g-1))//(10**g),0)for g in r(1,10)] is the number of the X,C,M,(X),(C),(M),((X)),((C)),((M))s in the number.

It then multiplies the occurrences with the value of the character and returns the sum of it.

I don't know if I understood the challenge correctly but I leave here a first contribution.

First I did a good research on Roman numerals on this site in Spanish and this other very interesting site in English

And then I dedicated myself to preparing the following code:

get_ascii_sum = functools.partial(lambda f, n: sum([ord(c) for c in f(n)]), lambda n: functools.reduce(lambda r, vg: (r + vg * vg, r - vg * vg), zip((lambda v, s: (v, [s[i] * ((n + 10 ** i) // (10 ** i * 5)) % 2 for i in range(len(s))], [((n % (10 ** i * 5)) // (10 ** i * 4)) + max(((n % (10 ** i * 5) % (10 ** i * 4)) + 10 ** (i - 1)) // (10 ** i), 0) for i in range(1, len(s))]))(values, symbols)), (0, num)))

• Hi, welcome to CGCC! What programming language is your code? Based on the syntax I think it's Python? Could you perhaps add a header to your answer with the programming language, as well as the byte-count, similar as other answers? And if it is indeed Python, you can remove a lot of your spaces to save bytes. :) Tips for golfing in 'all languages' might be interesting to read through. (And if it is indeed Python, there is also a separated tips page for that.) Jul 7 at 13:52