R [oman | everse] Notation polonaise

11

C'est l'année MDLXVII dans un monde où l'empire romain n'est jamais tombé et l'effondrement dans les âges sombres ne s'est jamais produit. En raison de la période prolongée de Pax Romana, la stabilité économique de l'empire a permis à la technologie de progresser à un rythme rapide.

Les Romains ont commencé à barboter avec les circuits et ont inventé une calculatrice ingénieuse qui ne nécessite pas l'utilisation d'un bouton "égal". Ils l'appellent "la notation polonaise romaine"

Pour effectuer un calcul, ils entrent d'abord leurs opérandes, puis l'opération.

Par exemple, 100 + 11 * 20 serait C XI XX * +.

aditionellement

Les Romains ont constaté qu'ils ont souvent besoin de faire plusieurs calculs en même temps, et préféreraient que la méthode retourne chaque valeur "sur la pile" dans une sorte de structure de type tableau / liste / tuple. (par exemple X I + X I - CC II +reviendrait [11, 9, 202])


Le défi est de développer un programme de calculateur capable de faire ces calculs.

Clarification : la notation soustractive est requise. Je n'avais pas réalisé que ce n'était pas une caractéristique reconnue dans l'ancien empire romain. La tâche était donc ambiguë et je m'en excuse.

Lignes directrices minimales

  • Votre sortie sera en chiffres arabes.
  • Vous avez seulement besoin de convertir des chiffres romains jusqu'à 5000.
  • Vous devrez prendre en charge les opérations +, -, /, * (addition, soustraction, division et multiplication).
  • Que la division soit basée sur une virgule flottante ou sur un entier est spécifique à l'implémentation. Soit fonctionne pour ce défi.
  • Votre sortie devra prendre en charge des nombres jusqu'à 4 milliards.
  • Réponse la plus courte dans l'ensemble, ET dans chaque langue gagne. Il s'agit d'un Code Golf Challenge mais j'adore la variété.

En cas d'égalité, des facteurs tels que la prise en charge des chiffres romains au-dessus de 5000 ou des opérations supplémentaires seront considérés comme la première soumission sera gagnante.

Jesse Daniel Mitchell
la source
1
Pouvons-nous prendre l'entrée comme une liste de chaînes, chacune ayant un nombre romain ou un opérateur?
user202729
l'entrée peut-elle être prise en minuscules ou doit-elle être en majuscules?
dzaima
1
@JesseDanielMitchell Remarque: essayez de ne pas modifier les règles et d'invalider les réponses existantes . Aussi, (comme d'habitude), je suggère de publier dans le bac à sable .
user202729

Réponses:

6

Python 2 + romain , 118 octets

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

Démo

Il ne peut pas être testé en ligne en raison du module qu'il utilise, mais vous pouvez voir comment l'exécuter ici (un programme complet acceptant les entrées de STDIN - une expression avec des guillemets - et imprimant la sortie vers STDOUT - sous la forme d'une liste , la pile). Utilise une version légèrement plus ancienne, car je ne prendrai pas la peine de créer un nouveau GIF pour seulement quelques octets:

GIF de démonstration

Pour installer le package, vous pouvez exécuter ce qui suit dans le terminal / ligne de commande:

pip install roman
M. Xcoder
la source
2
pyTester/Py.pyಠ_ಠ
totalement humain
@totallyhuman C'est juste un projet factice que j'ai fait juste pour ça ...
M. Xcoder
6

Haskell , 217 octets

-13 octets grâce à Bruce Forte. -73 octets grâce à Ø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

Essayez-le en ligne!

Implémentation manuelle, yay!

totalement humain
la source
2
J'ai réduit cela un peu (si près de battre le nouveau Python ...) Essayez-le en ligne!
Ørjan Johansen
1
Celui de Python a également été coupé. Mais si son argument selon lequel la notation soustractive n'a pas besoin d'être prise en charge est confirmé, alors il y a plus d'économies ici aussi.
Ørjan Johansen
1
Dans tous les cas, 3 octets supplémentaires avec l=1:4:5:9:map(10*)l.
ბიმო
Je me suis souvenu d'un truc de reste que j'ai trouvé pour convertir des chiffres romains, qui s'occupe automatiquement de la soustraction. Essayez-le en ligne!
Ørjan Johansen
2

JavaScript (Node) + romans + stk-lang , 74 octets

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

Renvoie une liste de bigintegers.

Exécution

Exécutez ce qui suit:

npm install romans
npm install stk-lang
node

Collez ensuite la fonction. Exemple:

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.

+ [email protected]
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.

+ [email protected]
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' ]
Conor O'Brien
la source
Combien de personnes utilisent un lambda comme invite?
Stan Strum
@StanStrum J'aime ça, et c'est la valeur par défaut pour les terminaux comme cmder
Conor O'Brien
Je ne le savais pas. Je suppose que je n'ai jamais dévié de $et >. Honnêtement, je l'aime bien
Stan Strum
2

Dyalog APL , 93 octets

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

Essayez-le en ligne!

116 octets sans le romain intégré

dzaima
la source
Woah, n'a jamais vu d'affectation modifiée dans un golf auparavant
Zacharý
@ Zacharý, c'est le seul moyen que je connaisse pour modifier une variable hors de sa portée dfns, elle a donc être utilisée ici.
dzaima
Pardonnez mon ignorance, mais qu'est-ce qu'une affectation modifiée?
caird coinheringaahing
@cairdcoinheringaahing var fn←arr- c'est équivalent à var ← var fn arr. Ici, il est utilisé à plusieurs endroits, a,←⍵celui qui s'ajoute à la variablea
dzaima
1

Python 3 , 280 206 octets

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

Essayez-le en ligne!

Cette fois avec le support de notation soustractive. La méthode cest le principal point d'entrée; l'autre est le soutien.

Modifier le journal:

  • 74 en baisse grâce à Ørjan
David Foerster
la source
Vous n'avez pas besoin des blocs d'indentation après ifet else.
Ørjan Johansen
En fait, permettez-moi de vous offrir cette astuce que j'ai trouvée une fois:n+=v-n%v*2
Ørjan Johansen
1
Vous pouvez également combiner les deux strutilisations. Essayez-le en ligne!
Ørjan Johansen
0

JavaScipt (ES6), 152 151 octets

1 octet enregistré grâce à 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

Cas de test

Explication (moins 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
Herman L
la source
Je suis sûr que cela 1e3fonctionne également et enregistre quelques octets.
user202729
0

Gelée , 82 octets

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

Essayez-le en ligne!

Publié à l'origine dans le chat .


Explication:

Parce que Jelly n'a pas de pile, j'ai mis la pile dans le registre.

Lorsque le programme démarre, la valeur de registre ®est 0, qui est traitée comme [0]aux fins de ce programme.


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

user202729
la source
-1

Python 3 , 216 187 octets

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

Essayez-le en ligne!

Parce qu'elle est apparue dans les commentaires de la question et de cette réponse et a probablement conduit à des votes négatifs: cette soumission ne prend pas en charge la notation soustractive. Justification: La notation soustractive était rarement utilisée dans l'Empire romain et n'a été popularisée que plus tard (voir Notation soustractive , paragraphe 3, dernière phrase). La tâche suppose un empire romain qui a développé des circuits intégrés programmables, pas un qui a subi les mêmes changements culturels que l'Europe du 13ème siècle. La description ne mentionne pas la notation soustractive et aucun des exemples ne l'utilise.

David Foerster
la source
Hm ... vous ne supportez pas les nombres comme CIV(104).
Ørjan Johansen
... je ne peux pas blâmer votre logique là-bas. : P
Ørjan Johansen
2
Agh, tu avais raison. Je n'avais pas pensé à l'ambiguïté possible, je ne savais pas que la notation soustractive n'était pas une caractéristique commune dans l'ancien empire romain.
Jesse Daniel Mitchell
1
J'ai effectivement envisagé de poser des questions sur la notation soustractive sous l'OP (et j'ai remarqué le manque d'exemple), mais j'ai été distrait. Si vous pensez à des ambiguïtés de définition dans les défis à venir, n'hésitez pas, il suffit de demander (répondre avec une mise en garde et un lien vers votre commentaire devrait faire si vous voulez poster). Maintenant, une décision est en vous devrait essayer de le réparer :)
Jonathan Allan