Reputation: 41
For a computer science assignment my goal is to convert a character string (the roman numeral) to an integer. I'm to write a function to do this in Matlab. My code to do this is shown below.
function [x] = roman2decimal(s)
s1 = substr1(s,1);
s2 = substr2(s,2,2);
s = substr2(s, 3, numel(s));
sum = 0;
if (s1~='')
%Case I - if any of these conditions are true
if (s1=='C' && s2=='M')
sum = sum + 900;
end
if (s1=='C' && s2=='D')
sum = sum + 400;
end
if (s1=='X' && s2=='C')
sum = sum + 90;
end
if (s1=='X' && s2=='L')
sum = sum + 40;
end
if (s1=='I' && s2=='X')
sum = sum + 9;
end
if (s1=='I' && s2=='V')
sum = sum + 4;
end
s=s1
s2=substr2(s, 3, numel(s))
end
% case 2 - no case 1 conditions were true
if(s1=='M')
sum = sum + 1000;
end
if(s1=='D')
sum = sum + 500;
end
if(s1=='C')
sum = sum + 100;
end
if(s1=='L')
sum = sum + 50;
end
if(s1=='X')
sum = sum + 10;
end
if(s1=='V')
sum = sum + 5;
end
if(s1=='I')
sum = sum + 1;
end
s1=s2
s=s2
sum
end
function [c]=substr1(s,pos)
if(pos >= 1 && numel(s) >= pos) c=s(pos);
else c='';
end
end % substr1
function [c]=substr2(s,pos1,pos2)
if(pos1 >=1 && pos2 >= pos1 && pos2 <= numel(s)) c=s(pos1:pos2);
else c='';
end
end % substr2
The issue I'm having is that when I call the function for a character string that's more than 2 characters long, s1 always computes to the second character in the string, e.g. for 'CM' s1=M, s2=M.
If I call the substr1 function outside of this function, it works fine (e.g. returns the first character in the string).
I was wondering if there was something wrong with my algorithm/syntax and if you could help?
Much appreciated.
Upvotes: 3
Views: 2459
Reputation: 79
This solution is in C and has passed all the 3999 test cases in LeetCode
int romanToInt(char* s) {
int i = 0, value = 0;
for (int i =0; s[i] != '\0'; i++)
{
switch(s[i]) {
case 'I':
if(s[i+1] != '\0' ){
if(s[i+1] == 'V' ||s[i+1] == 'X' )
value = value -1;
else
value = value+1;
}else {
value = value+1;
}
break;
case 'V':
value = value + 5;
break;
case 'X':
if(s[i+1] != '\0' ){
if(s[i+1] == 'L' ||s[i+1] == 'C' )
value = value -10;
else
value = value+10;
}else {
value = value+10;
}
break;
case 'L':
value = value + 50;
break;
case 'C':
if(s[i+1] != '\0' ){
if(s[i+1] == 'D' ||s[i+1] == 'M' )
value = value -100;
else
value = value+100;
}else {
value = value+100;
}
break;
case 'D':
value = value + 500;
break;
case 'M':
value = value + 1000;
break;
}
}
return value;
}
Upvotes: 1
Reputation: 21563
Here is an answer inspired by @Robert, yet quite different:
myStr = 'MCMLXXXVIII';
key = 'MDCLXVI';
values = [1000, 500,100,50,10,5,1];
% Calculate the 'weight' of each letter
[~, loc]=ismember(myStr,key)
relevantValues = values(loc);
% Determine whether we should substract or add
s = [-sign(diff(relevantValues)), 1];
%% To avoid zeros in s
while ~all(s)
f = find(s == 0);
s(f) = s(f+1);
end
s*relevantValues'
This vectorized approach minimizes the amount of string operations and avoids eval
statements.
Upvotes: 7