R [oman | everse] Notazione polacca


11

È l'anno MDLXVII in un mondo in cui l'impero romano non è mai caduto e il crollo nelle epoche buie non è mai avvenuto. A causa del lungo periodo di Pax Romana, la stabilità economica dell'impero ha permesso alla tecnologia di progredire rapidamente.

I romani hanno iniziato a dilettarsi con i circuiti e hanno inventato un calcolatore ingegnoso che non richiede l'uso di un pulsante "uguale". Lo chiamano "notazione polacca romana"

Per effettuare un calcolo, inseriscono prima i loro operandi, quindi l'operazione.

Ad esempio, 100 + 11 * 20 sarebbe C XI XX * +.

Inoltre

I romani hanno scoperto che spesso hanno bisogno di fare più calcoli contemporaneamente e preferirebbero che il metodo restituisse ogni valore "nello stack" in una sorta di struttura simile a matrice / elenco / tupla. (ad es. X I + X I - CC II +restituirebbe [11, 9, 202])


La sfida è sviluppare un programma di calcolatrice in grado di effettuare questi calcoli.

Chiarimento : è richiesta la notazione sottrattiva. Non mi ero reso conto che non era una caratteristica riconosciuta nell'antico impero romano. Il compito era quindi ambiguo e mi scuso.

Linee guida minime

  • Il tuo output sarà in numeri arabi.
  • Hai solo bisogno di convertire da numeri romani fino a 5000.
  • Dovrai supportare le operazioni +, -, /, * (addizione, sottrazione, divisione e moltiplicazione).
  • Se la divisione è basata su virgola mobile o su numeri interi è specifica dell'implementazione. O funziona per questa sfida.
  • L'output dovrà supportare numeri fino a 4 miliardi.
  • La risposta più breve in assoluto, E in ogni lingua vince. Questa è una sfida di golf del codice ma adoro la varietà.

In caso di pareggio, fattori come il supporto per numeri romani superiori a 5000 o operazioni aggiuntive saranno considerati la prima domanda vincente.


1
Possiamo prendere input come un elenco di stringhe, ognuna con un numero romano o un operatore?
user202729

l'input può essere preso in minuscolo o deve essere maiuscolo?
dzaima,

1
@JesseDanielMitchell Come nota ... cerca di non modificare le regole e invalidare le risposte esistenti . Inoltre, (come al solito) suggerisco di pubblicare nella Sandbox .
user202729

Risposte:


6

Python 2 + romano , 118 byte

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

dimostrazione

Non può essere testato online a causa del modulo che utilizza, ma puoi vedere come eseguirlo qui (un programma completo che accetta input da STDIN - un'espressione con virgolette - e stampa l'output su STDOUT - sotto forma di un elenco , lo stack). Utilizza una versione leggermente più vecchia, perché non mi preoccuperò di creare una nuova GIF per solo pochi byte:

Demo GIF

Per installare il pacchetto, è possibile eseguire quanto segue nella riga di comando / terminale:

pip install roman

2
pyTester/Py.pyಠ_ಠ
totalmente umano il

@totallyhuman È solo un progetto fittizio che ho realizzato proprio per questo ...
Mr. Xcoder,

6

Haskell , 217 byte

-13 byte grazie a Bruce Forte. -73 byte grazie 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

Provalo online!

Implementazione manuale, yay!


2
L'ho ridotto un po '(così vicino a battere il nuovo Python ...) Provalo online!
Ørjan Johansen,

1
Anche quello di Python è stato abbattuto. Ma se la sua tesi secondo cui la notazione sottrattiva non ha bisogno di essere supportata è confermata, allora anche qui ci sono più risparmi.
Ørjan Johansen,

1
In ogni caso, altri 3 byte con l=1:4:5:9:map(10*)l.
ბიმო

Mi sono ricordato di un trucco che ho trovato una volta per convertire i numeri romani, che si occupa automaticamente della sottrazione. Provalo online!
Ørjan Johansen


2

JavaScript (nodo) + romani + stk-lang , 74 byte

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

Restituisce un elenco di bigintegers.

Esecuzione

Eseguire quanto segue:

npm install romans
npm install stk-lang
node

Quindi incolla la funzione. Esempio:

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

Quante persone usano un lambda come prompt?
Stan Strum

@StanStrum Mi piace, ed è l'impostazione predefinita per terminali come cmder
Conor O'Brien,

Non lo sapevo. Immagino di non aver mai deviato da $e >. Onestamente, mi piace però
Stan Strum

2

Dyalog APL , 93 byte

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

Provalo online!

116 byte senza il romano incorporato


Woah, non ho mai visto un incarico modificato in un golf prima d'ora
Zacharý

@ Zacharý è l'unico modo che conosco per modificare una variabile dal suo ambito dfns, quindi doveva essere usato qui.
dzaima,

Perdona la mia ignoranza, ma cos'è un incarico modificato?
caird coinheringaahing

@cairdcoinheringaahing var fn←arr- è equivalente a var ← var fn arr. Qui è usato in più punti, a,←⍵essendo uno che si aggiunge alla variabilea
dzaima

1

Python 3 , 280 206 byte

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

Provalo online!

Questa volta con supporto per notazione sottrattiva. Il metodo cè il punto di ingresso principale; l'altro è supporto.

Modifica registro:


Non sono necessari i blocchi di rientro dopo ife else.
Ørjan Johansen

In realtà, lascia che ti offra questo trucco che ho trovato una volta:n+=v-n%v*2
Ørjan Johansen

1
Puoi anche combinare i due strusi. Provalo online!
Ørjan Johansen

0

JavaScipt (ES6), 152 151 byte

Salvato 1 byte grazie 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

Casi test

Spiegazione (meno giocata a 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

Sono abbastanza sicuro che 1e3funziona anche e salva alcuni byte.
user202729

0

Gelatina , 82 byte

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

Provalo online!

Originariamente pubblicato in chat .


Spiegazione:

Poiché Jelly non ha uno stack, ho inserito lo stack nel registro.

All'avvio del programma, il valore del registro ®è 0, che viene trattato come [0]ai fini di questo programma.


ị“+-×÷”;”/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 byte

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

Provalo online!

Perché è emerso nei commenti sia della domanda che di questa risposta e probabilmente ha portato a voti negativi: questa presentazione non supporta la notazione sottrattiva. Razionale: la notazione sottrattiva è stata usata raramente nell'impero romano e resa popolare solo in seguito (vedi Notazione sottrattiva , paragrafo 3, ultima frase). Il compito presume un impero romano che sviluppò circuiti integrati programmabili, non uno che subì gli stessi cambiamenti culturali dell'Europa del XIII secolo. La descrizione non menziona la notazione sottrattiva e nessuno degli esempi la utilizza.


Hm ... non stai supportando numeri come CIV(104).
Ørjan Johansen,

... non posso criticare la tua logica lì. : P
Ørjan Johansen,

2
Agh, avevi ragione. Non avevo pensato alla possibile ambiguità, non ero consapevole che la notazione sottrattiva non fosse una caratteristica comune nell'impero romano antico.
Jesse Daniel Mitchell,

1
In realtà ho pensato di chiedere una notazione sottrattiva sotto il PO (e ho notato la mancanza di un esempio), ma mi sono distratto. Se pensi alle ambiguità della definizione nelle sfide future, non esitare, chiedi semplicemente (rispondendo con un avvertimento e un link al tuo commento dovrebbe fare se vuoi pubblicare). Ora c'è una sentenza che dovresti provare a sistemare :)
Jonathan Allan il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.