Integer goes back and forth through time

17

4

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

Roman Numerals:
enter image description here
Here is a perhaps useful Roman Numeral Converter.

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.
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.

Test cases:

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

Kevin Cruijssen

Posted 2016-08-01T06:52:26.383

Reputation: 67 575

Related – Kevin Cruijssen – 2016-08-01T08:51:58.603

1@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. – Kevin Cruijssen – 2016-08-01T09:35:28.697

9999. Google says either or. – martin – 2016-08-01T09:51:25.347

1The test case 2222222222 isn't in the given range. Also I agree with 5362. – Neil – 2016-08-01T10:05:49.707

@Neil Ah oops, you're completely right. I'll change it to something else. – Kevin Cruijssen – 2016-08-01T10:06:27.233

@martin I'm a bit confused about the I with a macron. M is 1000, so what is (I)? In the link you gave for 9999 it seems to also be 1000.. – Kevin Cruijssen – 2016-08-01T10:18:11.653

@KevinCruijssen depending on where you look, 9000->IX+ macron - see here

– martin – 2016-08-01T10:24:18.257

1The title kinda sounds like a Stack Overflow C question. – user6245072 – 2016-08-01T12:02:08.970

3Is the word "fourth" in the title a pun? If not, it should be "forth". – Monty Harder – 2016-08-01T20:47:53.067

Answers

4

Mathematica, 181 173 166 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@#,"_"];
p=PadLeft;
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.

HiggstonRainbird

Posted 2016-08-01T06:52:26.383

Reputation: 56

1Welcome to PPCG! – betseg – 2016-08-01T22:07:47.043

@betseg Thank you! This was a fun first problem. – HiggstonRainbird – 2016-08-01T22:21:13.680

10

Python 3, 281 278 273 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)

jDomantas

Posted 2016-08-01T06:52:26.383

Reputation: 101

You can golf some bytes by replacing return 0 if n==0 else with return 0if n<1else – Gábor Fekete – 2016-08-01T09:57:49.057

Your golfed version has calls to f in it when the function's name is g. – Gábor Fekete – 2016-08-01T10:01:26.043

Change n//9*10>=10*l to n//9>=l to save some more. – Gábor Fekete – 2016-08-01T10:03:08.713

Fixed function name, I changed it to check if I golfed it correctly and forgot to change it back. – jDomantas – 2016-08-01T10:08:24.760

3

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.

martin

Posted 2016-08-01T06:52:26.383

Reputation: 1 335

3

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}

Value Ink

Posted 2016-08-01T06:52:26.383

Reputation: 10 608

2

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
set/ad=n/p%%10,p*=10,c=d+7^>^>4,d-=9*c,t+=%4*c,c=d+3^>^>3,d-=5*c,t+=%3*c+%2*(d^>^>2)+%1*(d^&3)

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.

Neil

Posted 2016-08-01T06:52:26.383

Reputation: 95 035

1

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.

Neil

Posted 2016-08-01T06:52:26.383

Reputation: 95 035

1

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

Elly G

Posted 2016-08-01T06:52:26.383

Reputation: 11

Welcome to PPCG, nice first answer! – Copper – 2016-08-02T11:07:13.580

1

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.

Frédéric

Posted 2016-08-01T06:52:26.383

Reputation: 2 059

0

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.

Gábor Fekete

Posted 2016-08-01T06:52:26.383

Reputation: 2 809