# R[oman|everse] Polish Notation

It is the year MDLXVII in a world in which the Roman Empire never fell, and the collapse into the dark ages never occurred. Due to the extended period of Pax Romana, the empire's economic stability enabled technology to progress at a rapid rate.

The Romans have begun to dabble with circuitry, and have invented an ingenious calculator that doesn't require the use of an "equals" button. They call it "Roman Polish Notation"

To make a calculation, they enter their operands first, then the operation.

For example, 100 + 11 * 20 would be C XI XX * +.

The Romans have found that they often need to make multiple calculations at the same time, and would prefer for the method to return every value "on the stack" in some sort of array/list/tuple-like structure. (e.g. X I + X I - CC II + would return [11, 9, 202])

The challenge is to develop a calculator program capable of making these computations.

Clarification: Subtractive Notation is required. I hadn't realized it wasn't recognized feature in the Ancient Roman empire. The task was therefore ambiguous, and I apologize.

Minimum Guidelines

• Your output will be in Arabic Numerals.
• You only need to convert from Roman Numerals up to 5000.
• You will need to support +, -, /, * operations (addition, subtraction, division, and multiplication).
• Whether division is floating point based or integer based is implementation specific. Either works for this challenge.
• Your output will need to support numbers up to 4 Billion.
• Shortest answer overall, AND in each language wins. This is a Code Golf Challenge but I love the variety.

In the event of a tie, factors like support for roman numerals above 5000 or additional operations will be considered the earliest submission will win.

• Can we take input as a list of strings, each have either a Roman number or an operator? – user202729 Dec 31 '17 at 16:16
• can the input be taken in lowercase, or does it have to be uppercase? – dzaima Dec 31 '17 at 16:22
• @JesseDanielMitchell As a note... try not to change rules and invalidate existing answers. Also, (as usual) I suggest posting in the Sandbox. – user202729 Jan 1 '18 at 2:42

# Python 2 + roman, 118 bytes

from roman import*
s=[]
for i in input().split():s+=[eval(s.pop(-2)+i+s.pop())if i in"+-/*"elsefromRoman(i)]
print s


### Demo

It cannot be tested online because of the module it makes use of, but you can see how to run this here (a full program accepting input from STDIN – an expression with quotes – and printing the output to STDOUT – in the form of a list, the stack). Uses a slightly older version, because I won't bother to create a new GIF for only a few bytes: To install the package, you can run the following in the Terminal / Command Line:

pip install roman

• pyTester/Py.py ಠ_ಠ – totallyhuman Dec 30 '17 at 22:49
• @totallyhuman It's just a dummy project that I made just for this... – Mr. Xcoder Dec 30 '17 at 22:50

-13 bytes thanks to Bruce Forte. -73 bytes thanks to Ørjan Johansen.

foldl(!)[].words

# Dyalog APL, 93 bytes

⎕CY'dfns'
a←⍬⋄{0::{a,←⍵}roman⍵⋄f←⍎'+-÷×'⌷⍨'+-/*'⍳⍵⋄r←f/¯2↑a⋄a↓⍨←¯2⋄a,←r}¨{1↓¨⍵⊂⍨⍵∊' '}' ',⍞⋄a


Try it online!

116 bytes without the roman built-in

• Woah, never saw modified assignment in a golf before – Zacharý Dec 31 '17 at 17:46
• @Zacharý it's the only way I know to modify a variable out of its dfns scope, so it had to be used here. – dzaima Dec 31 '17 at 18:05
• Forgive my ignorance, but what is modified assignment? – caird coinheringaahing Jan 1 '18 at 1:52
• @cairdcoinheringaahing var fn←arr - it's equivalent to var ← var fn arr. Here it's used in multiple places, a,←⍵ being one which appends ⍵ to the variable a – dzaima Jan 1 '18 at 1:55

# Python 3, 280 206 bytes

N=dict(I=1,V=5,X=10,L=50,C=100,D=500,M=1000)
def d(s):
n=0
for v in map(N.get,s):n+=v-n%v*2
return n
def c(w):
s=[]
for t in w.split():s+=[str(d(t)if tin N else eval(s.pop(-2)+t+s.pop()))]
return s


Try it online!

This time with subtractive notation support. Method c is the main entry point; the other is support.

Edit log:

• You don't need the indentation blocks after if and else. – Ørjan Johansen Jan 2 '18 at 1:12
• Actually, let me offer you this trick I once found: n+=v-n%v*2 – Ørjan Johansen Jan 2 '18 at 1:28
• You can also combine the two str uses. Try it online! – Ørjan Johansen Jan 2 '18 at 1:37

# JavaScipt (ES6), 152 151 bytes

Saved 1 byte thanks to user202729

p=>p.split .map(c=>s.push(eval("+-/*".indexOf(c)+1?(T=s.pop(),s.pop())+c+T:c.replace(/./g,c=>"+"+{I:1,V:5,X:10,L:50,C:100,D:500,M:1e3}[c]))),s=[])&&s


## Test cases

f=p=>p.split .map(c=>s.push(eval("+-/*".indexOf(c)+1?(T=s.pop(),s.pop())+c+T:c.replace(/./g,c=>"+"+{I:1,V:5,X:10,L:50,C:100,D:500,M:1e3}[c]))),s=[])&&s
console.log(f("C XI XX * +"))
console.log(f("X I + X I - CC II +"))

## Explanation (less golfed)

V={I:1,V:5,X:10,L:50,C:100,D:500,M:1e3}     // Values of the roman numerals
p=>(
s=[],                                      // Initialize the stack
p.split .map(c=>                         // For every part in the input:
"+-/*".indexOf(c)+1?                      //   If the input is an operator:
s.push(eval((T=s.pop(),s.pop())+c+T))    //     Evaluate the operator on the top of the stack
:                                         //   Else (if it is a roman numeral):
s.push(eval(c.replace(/./g,c=>"+"+V[c])))//     Push the sum of the characters' values
),s)                                       // return the stack

• I'm pretty sure that 1e3 also work and save some bytes. – user202729 Dec 31 '17 at 11:28

# Jelly, 82 bytes

ị“+-×÷”;”/v®ṫ-¤®ṖṖ¤;©
4Ḷ⁵*p1,5P€
Ḳµ“+-*/”W€i⁸Ñ⁸Ç¤¹?µ€ṛ®Ḋ


Try it online!

Explanation:

Because Jelly doesn't have a stack, I put the stack in the register.

When the program starts, the register value ® is 0, which is treated as  for the purposes of this program.


integer in range 1..4), apply it.

ị“+-×÷”                     Index to the string "+-×÷"
;”/                  Concatenate with the character "/",
which is Jelly splat operator.
v   ¤             Evaluate with parameter...
®                  the register's
ṫ                 tail
-                from -1. (2 last items)
®  ¤;        Concatenate with the register value,
ṖṖ            pop twice.
©       Store the result to register.

4Ḷ                  Lowered range of 4, gives [0,1,2,3].
⁵*                Raise to power of 10. Value = 1,10,100,1000.
p1,5            Calculate Cartesian product with [1,5].
Value = [1,1],[1,5],[10,1],[10,5],...
P€          Calculate product of each item.

Alternatively, ×þ1,5F would also work instead of p1,5P€.

to the stack (register).
i                  Find index of ...
Ð€                  each character ...
“IVXLCDM”                     in "IVXLCDM".
µ             With that value, (consider LIX ->
[50,1,10] for example)
I
Ḳµ“+-*/”W€i⁸Ñ⁸Ç¤¹?µ€ṛ®Ḋ

[TODO complete explanation]



# Python 3, 216 187 bytes

from operator import*
N=dict(I=1,V=5,X=10,L=50,C=100,D=500,M=1000)
def f(w):
s=[]
for t in w.split():s+=[str(sum(map(N.get,t)))if tin N else str(eval(s.pop(-2)+t+s.pop()))]
return s


Try it online!

Because it came up in the comments of both the question and this answer and likely led to down-votes: this submission doesn't support subtractive notation. Rationale: Subtractive notation was rarely used in the Roman Empire and only popularised later (see Subtractive Notation, paragraph 3, last sentence). The task presumes a Roman Empire that developed programmable integrated circuits, not one that underwent the same cultural changes as 13th century Europe. The description doesn't mention subtractive notation and none of the examples uses it.

• Hm... you're not supporting numbers like CIV (104). – Ørjan Johansen Dec 31 '17 at 2:13
• ...can't fault your logic there. :P – Ørjan Johansen Dec 31 '17 at 2:23
• Agh, you were right. I hadn't thought about the possible ambiguity, I wasn't aware subtractive notation wasn't a common feature in the Ancient Roman empire. – Jesse Daniel Mitchell Dec 31 '17 at 16:11
• I did actually consider asking about subtractive notation under the OP (and noticed the lack of an example), but got distracted. If you think of definition ambiguities in future challenges, don't hesitate, just ask (answering with a caveat and a link to your comment should do if you want to post). Now a ruling is in you should attempt to fix it up :) – Jonathan Allan Dec 31 '17 at 18:48