Umrechnerfunktion für römische Zahlen


13

Erstellen Sie die kürzeste Funktion, um eine Zeichenfolge aus römischen Ziffern in eine Ganzzahl umzuwandeln .

Die Regeln für jeden Buchstaben finden Sie auf der Wikipedia-Seite . Bei Buchstaben über 1.000 werden Klammern gesetzt, um den höheren Wert anzuzeigen.

Bedarf:

  • Muss römische Ziffern 1 in 500.000 konvertieren
  • Muss in weniger als einer Minute abgeschlossen sein
  • Verwendet keine integrierten Funktionen, die einen Vorteil bieten könnten (Beispiel: Eine Funktion, die römische Zahlen in Ganzzahlen konvertiert)
  • Ist eine Funktion

Die Funktion muss keine Brüche unterstützen. Jede ungültige Eingabe sollte die Nummer 0 zurückgeben.

Kürzeste Funktion gewinnt. Bei einem Gleichstand gewinnt derjenige mit den meisten Stimmen.

Testfälle

Eingang

III

Ausgabe

3


Eingang

IIII

Ausgabe

0


Eingang

XVI

Ausgabe

16


Eingang

(C)(D)(L)MMI

Ausgabe

452001

2
Es sei denn, ich vermisse etwas, (C)(D)(L)MMIwäre 452.001. Wie sind Sie auf Ihren Wert gekommen? Muss dies zusätzlich "falsche" Formulare unterstützen (zB ICstatt XCIX)?
Anon.

Unsachgemäß bedeutet für mich illegal und sollte daher 0 zurückgeben.
Martin York

@Anon: Die Nummer war ein Tippfehler, als ich den ursprünglichen dritten Testfall geändert habe. Es müssen keine falschen Formulare unterstützt werden, da dies als ungültige Eingabe angesehen wird.
Kevin Brown

1
Standardmäßig (und in der Spezifikation des Duplikats dieser Frage) ist es, dass ungültige Eingaben undefiniertes Verhalten sind. Da diese Frage vier Jahre alt ist und nur eine Antwort hatte, sollten wir die Anforderungen ändern?
Lirtosiast

1
@ Kevin Brown Ich sehe keine Quelle oder Erklärung für die in Klammern gesetzten Buchstaben. Ich denke, Sie sollten die Spezifikation so ändern, dass sie mit codegolf.stackexchange.com/q/16254/43319 übereinstimmt, und dann können die Antworten von dort hier migriert werden.
Adám

Antworten:


6

C ++: 914 855 Zeichen

#include<map>
#include<string>
#include<iostream>
#include<sstream>
#define I istream
#define T(C) if(C)throw int(1);
#define X(c,v,f,m) D[c]=v;P[c]=D[f];M[c]=m;
#define S second
using namespace std;typedef map<char,int>R;R D,P,M;struct U{U():t(0),l(0),a(0){}int t,l,a;operator int(){return t+l;}I&d(I&s){char c,b;s>>c;if(c=='('){s>>c>>b;T(b!=')')c+=32;}if(s){R::iterator f=D.find(c);T(f==D.end())if(P[c]==l){l=f->S-l;a=0;}else{T(l&&(f->S>l))a=l==f->S?a+1:1;T(a>M[c])t+=l;l=f->S;}}return s;}};I&operator>>(I&s,U&d){return d.d(s);}int main(){D[' ']=-1;X(73,1,32,3)X(86,5,73,1)X(88,10,73,3)X(76,50,88,1)X(67,100,88,3)X(68,500,67,1)X(77,1000,67,3)X(118,5000,77,1)X(120,10000,77,3)X(108,50000,120,1)X(99,100000,120,3)X(100,500000,99,1)X(109,1000000,99,3)string w;while(cin>>w){try{stringstream s(w);U c;while(s>>c);cout<<c<<"\n";}catch(int x){cout<<"0\n";}}}

Es könnte weiter komprimiert werden.

> ./a.exe
III
3
IIII
0
XVI
16
(C)(D)(L)MMI
452001

Etwas schönere Formatierung: 1582 Zeichen

#include<map>
#include<string>
#include<iostream>
#include<sstream>
#define I istream
#define T(C) if(C)throw int(1);
#define X(c,v,f,m) D[c]=v;P[c]=D[f];M[c]=m;
#define S second
using namespace std;

typedef map<char,int>      R;

R     D,P,M;

struct U
{
    U(): t(0), l(0), a(0) {}

    int  t,l,a;

    operator int()
    {
        return t + l;
    }
    I& d(I& s)
    {
        char c,b;
        s >> c;
        if (c == '(')
        {
            s >> c >> b;
            T(b != ')')
            c = tolower(c);
        }
        if (s)
        {
            R::iterator f = D.find(c);
            T(f == D.end())

            if (P[c] == l)
            {
                l = f->S - l;
                a = 0;
            }
            else
            {
                T(l&&(f->S > l))
                a=l==f->S?a+1:1;
                T(a>M[c])
                t   += l;
                l     = f->S;
            }
        }

        return s;
    }

};

I& operator>>(I& s,U& d)
{
    return d.d(s);
}

int main()
{
    D[' ']=-1;
    X(73,1,32,3)
    X(86,5,73,1)
    X(88,10,73,3)
    X(76,50,88,1)
    X(67,100,88,3)
    X(68,500,67,1)
    X(77,1000,67,3)
    X(118,5000,77,1)
    X(120,10000,77,3)
    X(108,50000,120,1)
    X(99,100000,120,3)
    X(100,500000,99,1)
    X(109,1000000,99,3)

    string w;
    while(cin >> w)
    {
        try
        {
            stringstream s(w);
            U    c;
            while(s >> c);
            cout << c << "\n";
        }
        catch(int x)
        {
            cout << "0\n";
        }
    }
}

Ich glaube nicht, dass Sie ein Leerzeichen zwischen den Makrofunktionen und ihren Definitionen brauchen.
Zacharý

4

Javascript, 317 Zeichen

function f(s){for(r=/\(?(.\)?)/g,t=e=0;a=r.exec(s);l=a[0].length,d='IXCMVLD'.indexOf(a[1][0]),e=e||d<0||l==2||d*4+l==3,t+='+'+(d>3?5:1)*Math.pow(10,d%4+3*(l>1)));t=t&&t.replace(/1(0*).(10|5)\1(?!0)/g,'$2$1-1$1');return e||/[^0](0*)\+(10|5)\1/.test(t)||/(\+10*)\1{3}(?!-)/.test(t)||/-(10*)\+\1(?!-)/.test(t)?0:eval(t)}

Erklärung:

function f(s){
      // iterate over every character grabbing parens along the way
  for(r=/\(?(.\)?)/g,t=e=0;a=r.exec(s);    
        // get a numerical value for each numeral and join together in a string
    l=a[0].length,
    d='IXCMVLD'.indexOf(a[1][0]),
    e=e||d<0||l==2||d*4+l==3,    // find invalid characters, and parens
    t+='+'+(d>3?5:1)*Math.pow(10,d%4+3*(l>1))
  );
      // reorder and subtract to fix IV, IX and the like
  t=t&&t.replace(/1(0*).(10|5)\1(?!0)/g,'$2$1-1$1');
  return e||
    /[^0](0*)\+(10|5)\1/.test(t)|| // find VV,IIV,IC,...
    /(\+10*)\1{3}(?!-)/.test(t)||  // find IIII,... but not XXXIX
    /-(10*)\+\1(?!-)/.test(t)      // find IVI,... but not XCIX
      ?0:eval(t)
}

Ohne Fehlererkennung sind es nur 180 Zeichen

function g(s){for(r=/\(?(.\)?)/g,t=0;a=r.exec(s);d='IXCMVLD'.indexOf(a[1][0]),t+='+'+(d>3?5:1)+'0'.repeat(d%4+3*(a[1].length>1)));return eval(t.replace(/(1(0*).(10|5)\2)/g,'-$1'))}

Das funktioniert genauso, aber hier ist eine bessere Formatierung:

function g(s){
  for(r=/\(?(.\)?)/g,t=0;a=r.exec(s);
    d='IXCMVLD'.indexOf(a[1][0]),
    t+='+'+(d>3?5:1)+'0'.repeat(d%4+3*(a[1].length>1))
  );
  return eval(t.replace(/(1(0*).(10|5)\2)/g,'-$1'))
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.