Otrzymujesz jako tekst poprawne wyrażenie matematyczne, jednak zapisane liczbami rzymskimi.
Twoim wyzwaniem jest zwrócić liczbę całkowitą będą wynikiem wyrażenia w systemie dziesiętnym. Algorytm powinien składać się z jak najmniejszej ilości znaków.
Wyrażenie może zawierać następujące znaki:
- operatory:
'+'
, '/'
, '-'
, '*'
, '='
, '(',
')'
- cyfry:
'C'
, 'D'
, 'I'
, 'L'
, 'M'
, 'V'
, 'X'
Przykłady:
RomanExpression("V+V=") = 10
, as 5 + 5 = 10
RomanExpression("IX=") = 9
, as 9 = 9
RomanExpression("(III+VI)*CM=") = 8100
, as (3 + 6) * 900 = 8100
- Dane wejściowe: string
- Poprawne wyrażenie matematyczne do rozwiązania
- Dane wyjściowe: integer
Uwaga, poniżej przedstawionych jest kilka rozwiązań. Nie przewijaj jeśli sam chcesz pogłówkować.
Rozwiązania z minimalną ilością znaków
Java:
570 znaków:
int RomanExpression(String e) {
int i = 0,k=e.length(),j=0;
String l="IVXLCDM",n="",u="";
while(i < k){
if(l.contains(e.charAt(i)+"")){
u="";
while(l.contains(e.charAt(i)+"") & i < k){
u+=e.charAt(i)+"";
i++;
}
int g=0,v=u.length(),t=0,o[]=new int[99];
o['I']=1;
o['V']=5;
o['X']=10;
o['L']=50;
o['C']=100;
o['D']=500;
o['M']=1000;
for(;t<v;t++){
char f=u.charAt(t);
if(t+1<v && o[f] < o[u.charAt(t+1)])
g-=o[f];
else g+=o[f];
}
n+=g;
}else{
n+=e.charAt(i)+"";
i++;
}
}
try{
return (int)Double.parseDouble(new javax.script.ScriptEngineManager().getEngineByName("js").eval(n.replace("=", ""))+"");
}catch(Exception t){
}
return 0;
}
636 znaków:
String O = "-+/*", T = "";
int r, l, x, a, b;
Stack<Integer> s = new Stack(), e = new Stack();
int RomanExpression(String S) {
for (char c : S.toCharArray()) {
if (c > 64) {
T += c;
++l;
continue;
}
if (l > 0) {
byte[] B = T.getBytes();
for (r = x = 0; x < l - 1;)
r += (s(B[x]) < s(B[x + 1]) ? -1 : 1) * s(B[x++]);
e.push(r + s(B[l - 1]));
}
T = "";
l = 0;
x = O.indexOf(c);
if (x > -1)
if (s.size() < 1)
s.push(x);
else {
while (s.size() > 0)
if (s.peek() / 2 >= x / 2)
e();
else
break;
s.push(x);
}
else if (c == 40)
s.push(-2);
else if (c == 41) {
while (s.peek() > -2)
e();
s.pop();
}
}
while (s.size() > 0)
e();
return e.pop();
}
void e() {
r = s.pop();
a = e.pop();
b = e.pop();
e.push(r < 1 ? b - a : r < 2 ? b + a : r < 3 ? b / a : b * a);
}
int s(byte c) {
return c < 68 ? 100 : c < 69 ? 500 : c < 75 ? 1 : c < 77 ? 50 : c < 78 ? 1000 : c < 87 ? 5 : 10;
}
C++:
418 znaków:
#define d double
#define c char
#define b return
#define w while
#define y *i
#define z y++
c y;
d m[99];
d F() {
w (y < 33) z;
d r = 0, p = 0, n;
if (y > 64) {
c *s = i;
w (y > 64) z;
c *e = i;
w (e-- - s)
n = m[*e-67],
r += n<p ? -n : n,
p = n;
b r;
}
if (y < 41)
b z, r = E(), z, r;
if (y > 43)
b z, -F();
b 0;
}
d T() {
d r = F();
w (y==42 || y==47)
r *= z-42 ? 1/F() : F();
b r;
}
d E() {
d r = T();
w (abs(y-44) < 2)
r -= (z-44) * T();
b r;
}
d RomanExpression(std::string e) {
m[0] = 100;
m[1] = 500;
m[6] = 1;
m[9] = 50;
m[10] = 1000;
m[19] = 5;
m[21] = 10;
i = &e[0];
b E();
}
419 znaków:
typedef std::string S;
int i, c, f = 8, g, l, v[7]{1,5,10,50,100,500,1000}, w[7]{9,0,0,2,2,4,4}, RomanExpression(S e) {
int h, k, a = 0, s = 0, m = 0, d = 0;
auto y = [&]() {
m ? g *= k : d ? g = k / g : 0;
m = d = 0;
k = g;
};
auto z = [&]() {
y();
a ? g += h : s ? g = h - g : 0;
a = s = 0;
h = g;
};
for (; i < e.size();)
if (l = f, f = S("IVXLCDM").find(c = e[i++]), (c -= 40) == 1 | c == 21)
return z(), g;
else
f + 1 ?
l + 1 ? 0 : g = 0, g += v[f], w[f] - l ? 0 : g -= 2*v[l] :
c == 3 ?
z(), a = 1 :
c == 5 ?
z(), s = 1 :
c == 2 ?
y(), m = 1 :
c == 7 ?
y(), d = 1 :
c ? 0 : g = RomanExpression(e);
}
Javascript:
152 znaków:
function RomanExpression(e) {
n = {I:1,V:5,X:10,L:50,C:100,D:500,M:1e3}
r = R = ''
for (i in e)
(u = n[t = e[i++]]) ? R -= u < n[e[i]] ? u : -u : e[i] && (r += R + t, R = '')
return ~~eval(r + R)
}
163 znaków:
function RomanExpression(s) {
h = {I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1e3}
c = s[i = t = 0]
n = ''
while (d = s[++i]) {
if (v = h[c]) t += v * 2 < h[d] ? -v : v
else {
n += t ? t + c : c
t = 0
}
c = d
}
return eval(n + t) | 0
}
Python:
I jak zwykle w potyczkach algorytmicznych, w których celem jest napisanie algorytmu z wykorzystaniem jak najmniejszej ilości znaków wygrywa Python
143 znaków:
def RomanExpression(e):
s = n = ''
for i in e:
if i > 'A':
n += i
else:
t = p = 0
for r in n:
x = 10 ** ( 205558 % ord(r) % 7 ) % 9995
t += x - 2 * p % x
p = x
s += (t > 0) * `t` + i
n = ''
return eval(s[:-1])
158 znaków:
def RomanExpression(e):
s=re.sub
e=s("(\w+)", r"(\1)", e[:-1])
for i in range(13):
e=s(
"IIXXCCIVXLCDMVXLCDM"[i::13], "+" + s(
" ", "0",
"4949491515151 ")[i::13], e
)
return eval(e)
Artykuł Zagadki algorytmiczne #2 – parser wyrażeń liczb rzymskich pochodzi z serwisu Notatnik programisty.