Fungsi konverter angka Romawi

13

Buat fungsi terpendek untuk mengonversi string angka Romawi menjadi bilangan bulat.

Aturan untuk setiap huruf dapat ditemukan di halaman Wikipedia . Huruf di atas 1.000 akan memiliki tanda kurung di sekitar mereka untuk memberi sinyal nilai yang lebih tinggi.

Persyaratan:

  • Harus mengonversi angka Romawi 1 hingga 500.000
  • Harus selesai dalam waktu kurang dari satu menit
  • Tidak menggunakan fungsi bawaan yang dapat memberikan keuntungan (Mis: Fungsi yang mengubah angka Romawi menjadi bilangan bulat)
  • Apakah fungsi

Fungsi tidak perlu mendukung pecahan. Setiap input yang tidak valid harus mengembalikan angka 0.

Fungsi terpendek menang. Dalam kasus seri, yang memiliki suara terbanyak menang.

Uji Kasus

Memasukkan

III

Keluaran

3


Memasukkan

IIII

Keluaran

0


Memasukkan

XVI

Keluaran

16


Memasukkan

(C)(D)(L)MMI

Keluaran

452001
Kevin Brown
sumber
2
Kecuali saya kehilangan sesuatu, (C)(D)(L)MMIakan menjadi 452.001. Bagaimana Anda mendapatkan nilai Anda? Selain itu, apakah ini perlu mendukung formulir "tidak patut" (misalnya, ICbukan XCIX)?
Anon.
Tidak layak bagi saya berarti ilegal dan karenanya harus mengembalikan 0.
Martin York
@ Anon: Nomornya adalah kesalahan ketik sejak saya mengubah kasus uji ketiga yang asli. Tidak perlu mendukung formulir yang tidak patut, karena akan dianggap sebagai input yang tidak valid.
Kevin Brown
1
Praktik standar (dan spesifikasi duplikat pertanyaan ini) adalah untuk input yang tidak valid menjadi perilaku yang tidak terdefinisi. Karena pertanyaan ini berumur empat tahun dan hanya memiliki satu jawaban, haruskah kita mengubah persyaratan?
lirtosiast
1
@KevinBrown Saya tidak melihat sumber atau penjelasan untuk surat tanda kurung. Saya pikir Anda harus mengubah spesifikasi agar sesuai dengan codegolf.stackexchange.com/q/16254/43319 dan kemudian jawaban dari sana dapat dimigrasikan di sini.
Adám

Jawaban:

6

C ++: 914 855 karakter

#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";}}}

Itu bisa dikompresi lebih lanjut.

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

Format yang sedikit lebih baik: 1582 char

#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";
        }
    }
}
Martin York
sumber
Saya tidak berpikir Anda membutuhkan ruang antara fungsi makro dan definisi mereka.
Zacharý
4

Javascript, 317 karakter

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)}

Penjelasan:

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)
}

Tanpa deteksi kesalahan hanya 180 karakter

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'))}

Ini bekerja dengan cara yang sama, tetapi di sini adalah format yang lebih baik:

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'))
}
BlueCheetah
sumber