Créer une calculatrice de chiffres romains

18

Créez une calculatrice de base pour les chiffres romains.

Exigences

  • Supports +, -, *,/
  • L'entrée et la sortie ne doivent s'attendre qu'à un seul préfixe soustracteur par symbole (c.-à-d. 3 ne peut pas l'être IIVcar il y en a deux Iavant V)
  • Manipulation du principe de soustraction en entrée et doit de sortie au soutien minimum conventions standards modernes, où seuls pouvoirs de dix sont soustraites des chiffres plus importants (par exemple I, X, Csont nécessaires soustracteurs mais non V, L, D) et la soustraction est jamais fait à partir d' un nombre plus 10x le soustracteur (par exemple IXdoit être pris en charge mais ICn'est pas requis).
  • L'entrée et la sortie doivent être de gauche à droite par ordre de valeur, en commençant par la plus grande (c.-à-d. 19 = XIXnon IXX, 10 est supérieur à 9)
  • De gauche à droite, aucune priorité d'opérateur, comme si vous utilisiez une calculatrice manuelle.
  • Prend en charge les entrées / sorties de nombres positifs entiers entre 1-4999 (pas besoin de V̅)
  • Aucune bibliothèque qui effectue la conversion des chiffres romains pour vous

À vous de décider

  • Sensibilité à la casse
  • Espaces ou aucun espace en entrée
  • Que se passe-t-il si vous obtenez une sortie décimale. Tronquer, pas de réponse, erreur, etc.
  • Que faire pour une sortie que vous ne pouvez pas gérer. Négatifs ou nombres trop grands à imprimer.
  • Que ce soit pour soutenir une utilisation plus libérale du principe de soustraction que l'exigence minimale.

Crédit supplémentaire

  • -50 - Poignée jusqu'à 99999 ou plus. Les symboles doivent inclure un vinculum

Exemple d'entrée / sortie

XIX + LXXX                 (19+80)
XCIX

XCIX + I / L * D + IV      (99+1/50*500+4)
MIV

Le code le plus court gagne.

Danny
la source
(99 + 1/50 * 500 + 4) = (99 + 10 + 4) = 113, mais votre échantillon d'entrée / sortie indique qu'il s'agit de MIV (1004).
Victor Stafusa
1
@Victor - opération stricte de gauche à droite - pas de règles de priorité - donc 99 + 1/50 * 500 + 4 doit être calculé comme ((((99 + 1) / 50) * 500) + 4)
La manipulation des numéros est-elle IM = 999requise?
Kendall Frey
@KendallFrey Je m'attendrais à ce que vous puissiez entrer IM. Que la sortie soit IMou CMXCIXpour 999 dépend de vous. Les deux répondent aux exigences.
Danny
2
IM n'est pas standard pour une utilisation moderne des chiffres romains. En règle générale, seuls les 4 et 9 de chaque ordre de grandeur (4, 9, 40, 90, 400, 900, etc.) sont effectués par soustraction. Pour 1999, MCMXCIX serait canonique, pas MIM ... regardez les crédits de n'importe quel film de cette année. Sinon, où ça finit? Devons-nous également prendre en charge d'autres soustractions non standard comme VL pour 45? Est-ce que IC avec un vinculum sur le C devrait être pris en charge comme 99999 pour le bonus?
Jonathan Van Matre

Réponses:

9

JavaScript (ES6), 238

c=s=>{X={M:1e3,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1}
n=eval('W='+s.replace(/[\w]+/g,n=>(o=0,n.replace(/[MDLV]|C[MD]?|X[CL]?|I[XV]?/g,d=>o+=X[d]),
o+';W=W')));o='';for(i in X)while(n>=X[i])o+=i,n-=X[i];return o}

Usage:

c("XIX + LXXX")
> "XCIX"
c('XCIX + I / L * D + IV')
> "MIV"

Version annotée:

/**
 * Process basic calculation for roman numerals.
 * 
 * @param {String} s The calculation to perform
 * @return {String} The result in roman numerals
 */
c = s => {
  // Create a lookup table.
  X = {
    M: 1e3, CM: 900, D: 500, CD: 400, C: 100, XC: 90, 
    L: 50,  XL: 40,  X: 10,  IX: 9,   V: 5,   IV: 4, I: 1
  };
  // Do the calculation.
  // 
  // The evaluated string is instrumented to as below:
  //   99+1/50*500+4 -> W=99;W=W+1;W=W/50;W=W*500;W=W+4;W=W
  //                 -> 1004
  n = eval('W=' + s.replace(
    // Match all roman numerals.
    /[\w]+/g,
    // Convert the roman number into an integer.
    n => (
      o = 0,
      n.replace(
        /[MDLV]|C[MD]?|X[CL]?|I[XV]?/g,
        d => o += X[d]
      ),
      // Instrument number to operate left-side operations.
      o + ';W=W'
    )
  ));

  // Convert the result into roman numerals.
  o = '';
  for (i in X)
    while (n >= X[i])
      o += i,
      n -= X[i];

  // Return calculation result.
  return o
}
Florent
la source
9

T-SQL, 1974 - 50 = 1924 octets

Je sais que jouer au golf en SQL équivaut à jouer 18 trous avec rien d'autre qu'un coin de sable, mais j'ai savouré le défi de celui-ci, et je pense que j'ai réussi à faire quelques choses intéressantes méthodologiquement.

Cela prend en charge le vinculum pour l'entrée et la sortie. J'ai adopté la convention d'utiliser un tilde de fin pour le représenter, donc V ~ est 5000, X ~ est 10000, etc. Après cela, il effectuera un encodage romain partiellement non standard de tout ce qui se trouve dans la plage prise en charge par INT.

Puisqu'il s'agit uniquement de mathématiques entières, tous les résultats non entiers sont arrondis implicitement.

DECLARE @i VARCHAR(MAX)
SET @i='I+V*IV+IX*MXLVII+X~C~DCCVI'
SELECT @i

DECLARE @t TABLE(i INT IDENTITY,n VARCHAR(4),v INT)
DECLARE @u TABLE(n VARCHAR(50),v INT)
DECLARE @o TABLE(n INT IDENTITY,v CHAR(1))
DECLARE @r TABLE(n INT IDENTITY,v INT,r VARCHAR(MAX))
DECLARE @s TABLE(v INT,s VARCHAR(MAX))
DECLARE @p INT,@x VARCHAR(4000)='SELECT ',@j INT=1,@m INT,@y INT,@z VARCHAR(2),@q VARCHAR(50)='+-/*~]%'
INSERT @t(n,v) VALUES('i',1),('iv',4),('v',5),('ix',9),('x',10),('xl',50),('l',50),('xc',90),('c',100),('cd',400),('d',500),('cm',900),('m',1000),('mv~',4000),('v~',5000),('mx~',9000),('x~',10000),('x~l~',40000),('l~',50000),('x~c~',90000),('c~',100000)
INSERT @u VALUES('%i[^i'+@q,-2),('%v[^vi'+@q,-10),('%x[^xvi'+@q,-20),('%l[^lxvi'+@q,-100),('%c[^clxvi'+@q,-200),('%d[^dclxvi'+@q,-1000),('%mx~%',-2010),('%x~l~%',-20060),('%x~c~%',-20110)
WHILE PATINDEX('%[+-/*]%', @i)!=0
BEGIN
    SET @p=PATINDEX('%[+-/*]%', @i)
    INSERT @o(v) SELECT SUBSTRING(@i,@p,1)
    INSERT @r(r) SELECT SUBSTRING(@i,1,@p-1)
    SET @i=STUFF(@i,1,@p,'')
END 
INSERT @r(r) SELECT @i
UPDATE r SET v=COALESCE(q.v,0) FROM @r r LEFT JOIN (SELECT r.r,SUM(u.v)v FROM @u u JOIN @r r ON r.r LIKE u.n GROUP BY r.r)q ON q.r=r.r
UPDATE r SET v=r.v+q.v FROM @r r JOIN (SELECT r.n,r.r,SUM((LEN(r.r)-LEN(REPLACE(r.r,t.n,REPLICATE(' ',LEN(t.n)-1))))*t.v) v FROM @r r JOIN @t t ON CHARINDEX(t.n,r.r) != 0 AND (LEN(t.n)=1 OR (LEN(t.n)=2 AND RIGHT(t.n,1)='~')) GROUP BY r.n,r.r) q ON q.r=r.r AND q.n = r.n
SELECT @m=MAX(n) FROM @o
SELECT @x=@x+REPLICATE('(',@m)+CAST(v AS VARCHAR) FROM @r WHERE n=1
WHILE @j<=@m
BEGIN
    SELECT @x=@x+o.v+CAST(r.v AS VARCHAR)+')'
    FROM @o o JOIN @r r ON r.n=o.n+1 WHERE o.n=@j
    SET @j=@j+1
END 
INSERT @s(v,s) EXEC(@x+',''''')
UPDATE @s SET s=s+CAST(v AS VARCHAR(MAX))+' = '
SET @j=21
WHILE @j>0
BEGIN
    SELECT @y=v,@z=n FROM @t WHERE i = @j
    WHILE @y<=(SELECT v FROM @s)
    BEGIN
        UPDATE @s SET v=v-@y,s=s+@z
    END  
    SET @j=@j-1
END
SELECT @x+' = '+UPPER(s) FROM @s

Je continue de bricoler avec une solution basée sur un ensemble pour remplacer une partie de la boucle WHILE qui pourrait réduire le nombre d'octets et être un exemple plus élégant de SQL idiomatique. Il y a également quelques octets à gagner en réduisant l'utilisation des alias de table au strict minimum. Mais comme il est essentiellement impossible de gagner dans cette langue, je suis surtout ici pour montrer ma tenue Don Quichotte. :)

SELECT @i en haut répète l'entrée:

I+V*IV+IX*MXLVII+X~C~DCCVI

Et le SELECT à la fin renvoie:

SELECT (((((1+5)*4)+9)*1047)+90706) = 125257 = C~X~X~V~CCLVII

Et vous pouvez le tester vous-même dans ce SQLFiddle

Et je reviendrai pour ajouter quelques commentaires sur la façon dont cela fonctionne, car pourquoi publier une réponse évidemment perdante si vous ne comptez pas l'exploiter à des fins éducatives?

Jonathan Van Matre
la source
2

Javascript - 482 476 caractères

String.prototype.m=String.prototype.replace;eval("function r(a){return a>999?'Mk1e3j899?'CMk900j499?'Dk500j399?'CDk400j99?'Ck100j89?'XCk90j49?'Lk50j39?'XLk40j9?'Xk10j8?'IX':a>4?'Vk5j3?'IV':a>0?'Ik1):''}".m(/k/g,"'+r(a-").m(/j/g,"):a>"));s=prompt();h=s.match(/\w+/gi);for(k in h)s=s.m(h[k],eval(eval("'0'+h[k].m(/IVu4pIXu9pXLu40pXCu90pCDu400pCMu900pMu1000pDu500pCu100pLu50pXu10pVu5pIu1')".m(/u/g,"/g,'+").m(/p/g,"').m(/")))+")");for(k in h)s="("+s;alert(r(Math.floor(eval(s))))

L'exemple d'entrée / sortie fonctionne:

XIX + LXXX -> XCIX
XCIX + I / L * D + IV -> MIV

Il gère également mal les grands nombres:

MMM+MMM -> MMMMMM
M*C -> MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

Et il accepte, mais n'exige pas, les espaces aussi.

Mais, depuis que je jouais au golf, il y a quelques problèmes:

  • Il ne valide pas si l'entrée est bien formée. Si l'entrée n'est pas bien formée, le comportement n'est pas défini (et en pratique, il est très bizarre et étrange).
  • Il tronque les nombres de fractions en sortie (mais il est capable de faire des calculs intermédiaires avec eux).
  • Il abuse vraiment de la fonction eval.
  • Il n'essaie pas de gérer les nombres négatifs.
  • Il est sensible à la casse.

Cette version alternative prend en charge des nombres supérieurs à 5000 jusqu'à 99999, mais elle comprend 600 598 584 caractères:

String.prototype.m=String.prototype.replace;eval("function r(a){return a>8zz?'XqCqk9e4j4zz?'Lqk5e4j3zz?'XqLqk4e4jzz?'Xqk1e4j89z?'IqXqk9e3j49z?'Vqk5e3j9z?'Mk1e3j8z?'CMk900j4z?'Dk500j3z?'CDk400jz?'Ck100j89?'XCk90j49?'Lk50j39?'XLk40j9?'Xk10j8?'IX':a>4?'Vk5j3?'IV':a>0?'Ik1):''}".m(/k/g,"'+r(a-").m(/j/g,"):a>").m(/q/g,"\u0305").m(/z/g,"99"));s=prompt();h=s.match(/\w+/gi);for(k in h)s=s.m(h[k],eval(eval("'0'+h[k].m(/IVu4pIXu9pXLu40pXCu90pCDu400pCMu900pMu1000pDu500pCu100pLu50pXu10pVu5pIu1')".m(/u/g,"/g,'+").m(/p/g,"').m(/")))+")");for(k in h)s="("+s;console.log(r(Math.floor(eval(s))))
Victor Stafusa
la source
Je ne pense pas que le -20 s'applique: voir vinculum
SeanC
D'accord avec @SeanCheshire ici. Pour le plus grand nombre manipulant, l'intention est d'ajouter un vinculum sur le chiffre à 1000 fois la valeur de ce qu'il est normalement. Peut-être qu'il devrait être plus grand qu'un -20, donc ça vaut la peine d'essayer pour les gens.
Danny
1
@Danny J'ai ajouté une version qui gère le vinculus, mais elle augmente le code en 116 caractères.
Victor Stafusa
2

Javascript 479 361 348 278 253

303 caractères - 50 pour les numéros de support jusqu'à 1 million, avec prise en charge de vinculum:

function p(s){s=s[r](/(^|[*\/+-])/g,"0;s$1=");for(i in v){f=R("\\b"+i);while(f.test(s))s=s[r](f,v[i]+"+")}eval(s+"0");h="";for(i in v)while(s>=v[i]){h+=i;s-=v[i]}return h}v={M̅:1e6,D̅:5e5,C̅:1e5,L̅:5e4,X̅:1e4,V̅:5e3,M:1e3,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1};r="replace";R=RegExp

Utilisation: p(text)par exemple, p('XIX + LXXX')retours XCIX.

Code avec commentaires explicatifs:

// Array mapping characters to values
v={M¯:1e6,D¯:5e5,C¯:1e5,L¯:5e4,X¯:1e4,V¯:5e3,M:1e3,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1};
// Shortcut for String.replace
r='replace';
R=RegExp;

// The heart of the program
function p(s) {
    // Replace operators with ";s+=", ";s-=", and so on
    s=s[r](/(^|[*\/+-])/g,'0;s$1=');
    // Loop over the character map and replace all letters with numbers
    for(i in v){
        f=R('\\b'+i);
        while(f.test(s))
            s=s[r](f, v[i]+'+')
    }
    eval(s+'0');
    // Set up our return string
    h='';
    // Replace digits with characters
    for(i in v)
        while(s>=v[i]) {
            h+=i;
            s-=v[i];
        }
    return h;
}

Cela fonctionne pour les échantillons donnés et pour tous les autres que j'ai essayés. Exemples:

XIX + LXXX = XCIX
XCIX + I / L * D + IV = MIV
XL + IX/VII + II * XIX = CLXXI
CD + C + XL + X + I = DLI
M̅ + I = M̅I
MMMM + M = V̅
élixénide
la source
2

Ruby 2.1, 353 (et de nombreuses autres itérations) , 295 - 50 = 245

La manipulation du vinculum ajoute ~ 23 caractères.

Cela gère "IL" ou "VM" dans l'entrée, et échoue sans erreur sur les négatifs (va en pouces élevés) ou décimales (tronquées), ou tout espace. Maintenant, gère également un premier nombre négatif (bien que si le total est négatif, il échoue toujours mal). Échoue également mal si vous commencez par * ou / ou si le résultat est supérieur ou égal à 4 millions.

Utilise Object # send pour la fonctionnalité "calculatrice manuelle".

m=%w{I V X L C D M V̅ X̅ L̅ C̅ D̅ M̅};n=m.zip((0..12).map{|v|(v%2*4+1)*10**(v/2)}).to_h
d=0
gets.scan(/([-+*\/])?([A-Z̅]+)/){|o,l|f=t=0
l.scan(/.̅?/){t-=2*f if f<v=n[$&]
t+=f=v}
d=d.send o||:+,t}
7.downto(1){|v|z=10**v
y=(d%z)*10/z
q,w,e=m[v*2-2,3]
$><<(y>8?q+e : y<4?q*y : y<5?q+w : w+q*(y-5))}

Non golfé:

m=%w{I V X L C D M V̅ X̅ L̅ C̅ D̅ M̅} # roman numerals
n=m.zip((0..12).map{|v|(v%2*4+1)*10**(v/2)}).to_h # map symbols to values
d=0
gets. # get input and...
  scan(/([-+*\/])?([A-Z̅]+)/) { |l,o|  # for each optional operator plus number
    f=t=0
    l.scan(/.̅?/){                           # read the number in one letter at a time
      t -= 2 * f if f < (v=n[$&])           # if the number's greater than the prev, subtract the prev twice since you already added it
      t += (f = v)                          # add this, and set prev to this number
    }
    d = d.send((o || :+), t)                # now that we've built our number, "o" it to the running total (default to +)
}
7.upto(1) { |v|                        # We now print the output string from left to right
  z = 10**v                            # z = [10, 100, 1000, etc.]
  y = (d%z)*10/z                       # if d is 167 and z is 100, y = 67/10 = 6 
  q,w,e = m[v*2-2,3]                   # q,w,e = X, L, C
  $><< (                               # print: 
    y>8 ? q+e :                        # if y==9,    XC
      y<4 ? q*y :                      # if y<4,     X*y
        y>3 ? q+w :                    # if y==4,    XL
          q*(y-5)                      # else,       L + X*(y-5)
  )
}
Pas que Charles
la source
2

Python 2 - 427 418 404 401 396 395 392 caractères

Lit à partir de l'entrée standard. Il ne gère que les majuscules (pourrait le rendre insensible à la casse au prix de 8 caractères supplémentaires) et nécessite des espaces. Ne fait aucune validation - je n'ai pas testé pour voir comment il se casse dans divers cas. Il gère cependant des nombres comme VC = 95.

N=['?M','DC','LX','VI'];t=0;o='+'
for q in raw_input().split():
 if q in"+-*/":o=q;continue
 n=s=0;X=1
 for l in q:
  x=''.join(N).find(l);v=(5-x%2*4)*10**(3-x/2)
  if X<x:n+=s;s=v;X=x
  elif X>x:n+=v-s;s=0
  else:n+=v+s;s=0
 exec"t"+o+"=n+s"
r=t/1000*'M'
for p,d in enumerate("%04d"%(t%1e3)):
 i="49".find(d);g=N[p]
 if i<0:
  if'4'<d:r+=g[0]
  r+=int(d)%5*g[1]
 else:r+=g[1]+N[p-i][i]
print r

Et la version non golfée:

# Numerals grouped by powers of 10
N = ['?M','DC','LX','VI']
# Start with zero plus whatever the first number is
t = 0
o = '+'
for q in raw_input().split():
    if q in "+-*/":
        # An operator; store it and skip to the next entry
        o = q
        continue
    # n holds the converted Roman numeral, s is a temp storage variable
    n = s = 0
    # X stores our current index moving left-to-right in the string '?MDCLXVI'
    X = 1
    for l in q:
        # x is the index of the current letter in '?MDCLXVI'
        x = ''.join(N).find(l)
        # Calculate the value of this letter based on x
        v = (5 - x%2 * 4) * 10 ** (3 - x/2)
        if X < x:
            # We're moving forward in the list, e.g. CX
            n += s      # Add in any previously-stored value
            s = v       # Store this value in case we have something like CXL
            X = x       # Advance the index
        elif X > x:
            # Moving backward, e.g. XC
            n += v - s  # Add the current value and subtract the stored one
            s=0
        else:
            # Same index as before, e.g. XX
            n += v + s  # Add the current value and any stored one
            s = 0
    # Update total using operator and value (including leftover stored value
    # if any)
    exec "t" + o + "=n+s"

# Now convert the answer back to Roman numerals
# Special-case the thousands digit
r = t / 1000 * 'M'
# Loop over the number mod 1000, padded with zeroes to four digits (to make
# the indices come out right)
for p, d in enumerate("%04d" % (t % 1e3)):
    i = "49".find(d)
    g = N[p]
    if i < 0:
        # i == -1, thus d isn't '4' or '9'
        if '4' < d:
            # >= 5, so add the 5's letter
            r += g[0]
        # ... plus (digit % 5) copies of the 1's letter
        r += int(d) % 5 * g[1]
    else:
        # If it's a 4 or 9, add the 1's letter plus the appropriate
        # larger-valued letter
        r += g[1] + N[p-i][i]
print r

J'ai l'impression que Perl aurait été mieux, mais je n'en sais pas assez. Pour un premier coup au golf de code, cependant, je me sens assez bien à ce sujet.

DLosc
la source
1

PHP - 549 525 524 520 octets

Rien de trop innovant: normalise les opérateurs pour assurer la priorité de gauche à droite, convertit Roman en décimal, s'exécute evalsur l'instruction, par exemple XCIX + I / L * D + IV est converti en quelque chose comme return (((((+90 +9) + (+1)) / (+50)) * (+500)) + (+4)); , puis convertit la décimale en romain.

  • les résultats finaux sont tronqués
  • réponses moins de 1 reviennent en blanc
  • les résultats ne sont pas définis en cas de saisie incorrecte
$f='str_replace';$g='str_split';$c=array('M'=>1e3,'CM'=>900,'D'=>500,'CD'=>400,'C'=>100,'XC'=>90,'L'=>50,'XL'=>40,'X'=>10,'IX'=>9,'V'=>5,'IV'=>4,'I'=>1);$j='['.$f(array('+','-','*','/'),array('])+[','])-[','])*[','])/['), $argv[1]).'])';$j=str_repeat('(',substr_count($j,')')).$j;$j=$f('[','(',$j);$j=$f(']',')',$j);foreach($g('IVIXXLXCCDCM',2)as$w)$j=$f($w,'+'.$c[$w],$j);foreach($g('IVXLCDM')as$w)$j=$f($w,'+'.$c[$w],$j);$k=eval('return '.$j.';');$l='';foreach($c as$a=>$b){while($k>=$b){$l.=$a;$k-=$b;}}print$l."\n";

par exemple

$ php roman.php 'XCIX + I / L * D + IV' — test case
MIV                                     — 1004

$ php roman.php 'XXXII * LIX'           — 32 × 59
MDCCCLXXXVIII                           — 1888

la source
0

Python - 446 octets

Cela pourrait être considérablement amélioré. J'ai senti que je devais faire le premier swing avec Python. Il fait 3 choses au premier passage

  1. symbolise les nombres et les opérateurs
  2. évalue les nombres et agrandit la table des symboles xpour inclure toutes les combinaisons possibles rencontrées (même si elles ne sont pas utilisées). Par exemple, pendant la XIXlex, les valeurs partielles de"X":10 , "XI":11et "XIX":19sont ajoutés à la table des symboles
  3. insère des parens imbriqués pour appliquer l'évaluation de gauche à droite

À la fin, il appelle eval à la chaîne d'origine (sauf avec des parenthèses ajoutées) et lui donne la table des symboles.

Ensuite, je viens de coller dans une solution connue pour convertir un entier en romain, car j'ai travaillé assez longtemps sur cela ... n'hésitez pas à vous améliorer pour que j'apprenne quelque chose de nouveau :)

m = zip ((1000,900,500,400,100,90,50,40,10,9,5,4,1),
(«M», «CM», «D», «CD», «C», «XC», «L», «XL», «X», «IX», «V», «IV», « JE'))
def doit (s):
 x = {'M': 1e3, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}; y = [] ; z = ''; a = '0'; s = '+' + s
 pour c dans s.upper ():
  si c dans x:
   z + = c; y.append (x [c])
   si len (y)> 1et y [-1]> y [-2]: y [-2] * = - 1
   x [z] = somme (y)
  elif c dans "+ / * -": a = '(' + a + z + ')' + c; y = []; z = ''
 a + = z; i = eval (a, x); r = ''
 pour n, c en m: d = int (i / n); r + = c * d; i- = n * d
 retour r


imprimer doit ("XIX + LXXX")
print doit ("XCIX + I / L * D + IV")
Mark Lakata
la source