R [oman | everse] Notación polaca


11

Es el año MDLXVII en un mundo en el que el Imperio Romano nunca cayó, y el colapso en la edad oscura nunca ocurrió. Debido al extenso período de Pax Romana, la estabilidad económica del imperio permitió que la tecnología progresara a un ritmo rápido.

Los romanos han comenzado a incursionar en los circuitos y han inventado una calculadora ingeniosa que no requiere el uso de un botón "igual". Lo llaman "notación romana polaca"

Para hacer un cálculo, primero ingresan sus operandos, luego la operación.

Por ejemplo, 100 + 11 * 20 sería C XI XX * +.

Adicionalmente

Los romanos han descubierto que a menudo necesitan hacer múltiples cálculos al mismo tiempo, y preferirían que el método devuelva cada valor "en la pila" en algún tipo de estructura tipo matriz / lista / tupla. (por ejemplo X I + X I - CC II +, devolvería [11, 9, 202])


El desafío es desarrollar un programa de calculadora capaz de realizar estos cálculos.

Aclaración : se requiere notación sustractiva. No me había dado cuenta de que no era una característica reconocida en el antiguo imperio romano. La tarea, por lo tanto, era ambigua, y me disculpo.

Pautas mínimas

  • Su salida estará en números arábigos.
  • Solo necesita convertir de números romanos hasta 5000.
  • Deberá admitir operaciones +, -, /, * (suma, resta, división y multiplicación).
  • Si la división está basada en coma flotante o en número entero es específica de la implementación. Cualquiera de los dos funciona para este desafío.
  • Su producción deberá admitir números de hasta 4 mil millones.
  • La respuesta más corta en general, Y gana en cada idioma. Este es un Code Golf Challenge pero me encanta la variedad.

En caso de empate, se considerarán factores como el soporte para números romanos superiores a 5000 u operaciones adicionales, la primera entrega ganará.


1
¿Podemos tomar la entrada como una lista de cadenas, cada una con un número romano o un operador?
user202729

¿Se puede tomar la entrada en minúsculas o en mayúscula?
dzaima

1
@JesseDanielMitchell Como nota ... intente no cambiar las reglas e invalidar las respuestas existentes . Además, (como de costumbre) sugiero publicar en el Sandbox .
user202729

Respuestas:


6

Python 2 + romano , 118 bytes

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

Manifestación

No se puede probar en línea debido al módulo que utiliza, pero puede ver cómo ejecutar esto aquí (un programa completo que acepta la entrada de STDIN, una expresión con comillas, e imprime la salida en STDOUT) en forma de lista , la pila). Utiliza una versión un poco más antigua, porque no me molestaré en crear un nuevo GIF para solo unos pocos bytes:

GIF de demostración

Para instalar el paquete, puede ejecutar lo siguiente en la Terminal / Línea de comando:

pip install roman

2
pyTester/Py.pyಠ_ಠ
totalmente humano

@totallyhuman Es solo un proyecto ficticio que hice solo para esto ...
Sr. Xcoder

6

Haskell , 217 bytes

-13 bytes gracias a Bruce Forte. -73 bytes gracias a Ørjan Johansen.

foldl(!)[].words
s@ ~(x:y:z)!n=last$(a n:s):[y`f`x:z|(f,c)<-zip[(+),(-),(*),(/)]"+-*/",n==[c]]
a s=last$0:[n+a(drop(length x)s)|(n,x)<-zip l$words"I IV V IX X XL L XC C CD D CM M",x<=s,x++"Y">s]
l=[1,4,5,9]++map(10*)l

Pruébalo en línea!

Implementación manual, yay!


2
Lo reduje un poco (tan cerca de vencer al nuevo Python ...) ¡ Pruébelo en línea!
Ørjan Johansen

1
El Python también fue cortado. Pero si se mantiene su argumento de que la notación sustractiva no necesita ser respaldada, entonces también hay más ahorros aquí.
Ørjan Johansen

1
En cualquier caso, otros 3 bytes con l=1:4:5:9:map(10*)l.
ბიმო

Recordé un truco restante que una vez encontré para convertir números romanos, que se encarga de restar automáticamente. Pruébalo en línea!
Ørjan Johansen


2

JavaScript (Nodo) + romanos + stk-lang , 74 bytes

s=>(R=require)("stk-lang")(s.replace(/\w+/g,R("romans").deromanize)).stack

Devuelve una lista de bigintegers.

Ejecución

Ejecute lo siguiente:

npm install romans
npm install stk-lang
node

Luego pegue la función. Ejemplo:

C:\Users\conorob\Programming\golf-new\roman
λ npm install romans
npm WARN saveError ENOENT: no such file or directory, open 'C:\Users\conorob\Programming\package.json'
npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\conorob\Programming\package.json'
npm WARN Programming No description
npm WARN Programming No repository field.
npm WARN Programming No README data
npm WARN Programming No license field.

+ romans@1.0.0
added 1 package in 0.801s

C:\Users\conorob\Programming\golf-new\roman
λ npm install stk-lang
npm WARN saveError ENOENT: no such file or directory, open 'C:\Users\conorob\Programming\package.json'
npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\conorob\Programming\package.json'
npm WARN Programming No description
npm WARN Programming No repository field.
npm WARN Programming No README data
npm WARN Programming No license field.

+ stk-lang@1.0.0
added 1 package in 0.847s

C:\Users\conorob\Programming\golf-new\roman
λ node
> s=>(R=require)("stk-lang")(s.replace(/\w+/g,R("romans").deromanize)).stack
[Function]
> f=_
[Function]
> f("X I + X I - CC II +").map(e => e.toString())
[ '11', '9', '202' ]
> f("C XI XX * +").map(e => e.toString())
[ '320' ]
> f("MMMM M I - +").map(e => e.toString())
[ '4999' ]

¿Cuántas personas usan un lambda como prompt?
Stan Strum

@StanStrum Me gusta, y es el valor predeterminado para terminales como cmder
Conor O'Brien

No lo sabia. Supongo que nunca me he desviado $y >. Sinceramente, me gusta, sin embargo
Stan Strum

2

Dyalog APL , 93 bytes

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

Pruébalo en línea!

116 bytes sin el romano incorporado


Woah, nunca vi asignación modificada en un golf antes
Zacharý

@ Zacharý es la única forma en que sé modificar una variable fuera de su alcance dfns, por lo que tuvo que usarse aquí.
dzaima

Perdona mi ignorancia, pero ¿qué es la asignación modificada?
caird coinheringaahing

@cairdcoinheringaahing var fn←arr: es equivalente a var ← var fn arr. Aquí se usa en varios lugares, a,←⍵siendo uno que se agrega a la variablea
dzaima el

1

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 t[0]in N else eval(s.pop(-2)+t+s.pop()))]
	return s

Pruébalo en línea!

Esta vez con soporte de notación sustractiva. El método ces el principal punto de entrada; El otro es el apoyo.

Editar registro:


No necesita los bloques de sangría después ify else.
Ørjan Johansen

En realidad, déjame ofrecerte este truco que una vez encontré:n+=v-n%v*2
Ørjan Johansen el

1
También puedes combinar los dos strusos. Pruébalo en línea!
Ørjan Johansen

0

Javascipt (ES6), 152 151 bytes

Guardado 1 byte gracias a 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

Casos de prueba

Explicación (menos golf)

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

Estoy bastante seguro de que 1e3también funciona y guarda algunos bytes.
usuario202729

0

Gelatina , 82 bytes

ị“+-×÷”;”/v®ṫ-¤®ṖṖ¤;©
4Ḷ⁵*p1,5P€
“IVXLCDM”iЀị¢µIN‘Ṡæ.µ®;©
Ḳµ“+-*/”W€i⁸Ñ⁸Ǥ¹?µ€ṛ®Ḋ

Pruébalo en línea!

Publicado originalmente en el chat .


Explicación:

Como Jelly no tiene una pila, puse la pila en el registro.

Cuando se inicia el programa, el valor de registro ®es 0, que se trata como [0]a los fines de este programa.


ị“+-×÷”;”/v®ṫ-¤®ṖṖ¤;©       Link 1: Given an operator index (an
                            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Ḷ⁵*p1,5P€          Link 2: Niladic, generate [1,5,10,50,...]
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€.

“IVXLCDM”iЀị¢µIN‘Ṡæ.µ®;©   Link 3: Given roman number, push it
                            to the stack (register).
         i                  Find index of ...
          Ѐ                  each character ...
“IVXLCDM”                     in "IVXLCDM".
            ị¢              Index to last link. (link 2)
              µ             With that value, (consider LIX ->
                            [50,1,10] for example)
               I             
Ḳµ“+-*/”W€i⁸Ñ⁸Ǥ¹?µ€ṛ®Ḋ

[TODO complete explanation]


-1

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 t[0]in N else str(eval(s.pop(-2)+t+s.pop()))]
	return s

Pruébalo en línea!

Debido a que surgió en los comentarios tanto de la pregunta como de esta respuesta y probablemente condujo a votos negativos: esta presentación no admite la notación sustractiva. Justificación: la notación sustractiva rara vez se usó en el Imperio Romano y solo se popularizó más tarde (ver Notación sustractiva , párrafo 3, última oración). La tarea supone un Imperio Romano que desarrolló circuitos integrados programables, no uno que experimentó los mismos cambios culturales que la Europa del siglo XIII. La descripción no menciona la notación sustractiva y ninguno de los ejemplos la usa.


Hm ... no estás apoyando números como CIV(104).
Ørjan Johansen

... no puedo criticar tu lógica allí. : P
Ørjan Johansen

2
Agh, tenías razón. No había pensado en la posible ambigüedad, no sabía que la notación sustractiva no era una característica común en el antiguo imperio romano.
Jesse Daniel Mitchell

1
De hecho, consideré preguntar sobre la notación sustractiva bajo el OP (y noté la falta de un ejemplo), pero me distraje. Si piensa en ambigüedades de definición en desafíos futuros, no lo dude, solo pregunte (responder con una advertencia y un enlace a su comentario debería hacerlo si desea publicar). Ahora hay un fallo en el que debes intentar arreglarlo :)
Jonathan Allan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.