Parses string with roman numerals.
Pass the string in any case as argument.
This version parses and “non-well-formed” roman numerals (like IIIII
or MIM
) as well.
function( | |
a // string | |
/* I just like when function's length property return something meaningful */ | |
){ | |
// Processing each char of `a` starting from the end of string: | |
for( | |
// Define the variables: | |
// v - value. To be assigned later | |
// s - sum | |
// i - iterator, length of the arg | |
var v, s = 0, i = a.length | |
; | |
// decrease iterator with post-decrement | |
i-- | |
; | |
// add the following to sum: | |
s += | |
// stored is more than following expression... | |
v > ( | |
// ...where current value is re-assigned. | |
// Here we define an array using elision | |
// and right after that get its value on key that is an integer: | |
v = [100,500,,,,,1,,,50,1e3,,,,,,,,,5,,10][ | |
// Get the char at the `i` offset and treat it as it was an integer in 36-based notation. | |
// The good thing: we don't need to use lo-ong toUpperCase :) | |
// And then decrease it by 12. This makes the array declaration slightly shorter | |
parseInt(a.charAt(i), 36) - 12 | |
] | |
// Here we get a positive value if char was one of: "IVXLCDMivxlcdm" and undefined else | |
// Using the subtraction check if this value is less than previous | |
// (Considering the fact we're parsing string from the tail, this is not the previous but *next* char) | |
// If there was no previous value, the whole subtraction gives NaN and comparation gives false | |
) ? | |
// If yes (i.e. IX or CM) we should subtract the current value from the sum | |
-v | |
: | |
// If no (i.e. XX or L{end-of-string}) we should add the current value to the sum | |
// If `v` is a NaN here, the sum will be NaN either. Garbage In Garbage Out, hehe. | |
// Uncomment ~~ if you don't like this behavior, there's still bytes left. | |
/* ~~ */ v | |
) | |
/* empty loop body */ | |
; | |
// return the sum | |
return s | |
} |
function(a){for(var v,s=0,i=a.length;i--;s+=v>(v=[100,500,,,,,1,,,50,1e3,,,,,,,,,5,,10][parseInt(a.charAt(i),36)-12])?-v:v);return s} |
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
Version 2, December 2004 | |
Copyright (C) 2011 subzey <[email protected]> | |
Everyone is permitted to copy and distribute verbatim or modified | |
copies of this license document, and changing it is allowed as long | |
as the name is changed. | |
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
0. You just DO WHAT THE FUCK YOU WANT TO. |
{ | |
"name": "parseRoman", | |
"description": "Parses roman numerals", | |
"keywords": [ | |
"roman", | |
"numeral", | |
"parse" | |
] | |
} |
<!DOCTYPE html> | |
<title>parseRoman</title> | |
<div>Expected value: <b>1986,1999,NaN</b></div> | |
<div>Actual value: <b id="ret"></b></div> | |
<script> | |
// write a small example that shows off the API for your example | |
// and tests it in one fell swoop. | |
var myFunction = function(a){for(var v,s=0,i=a.length;i--;s+=v>(v=[100,500,,,,,1,,,50,1e3,,,,,,,,,5,,10][parseInt(a.charAt(i),36)-12])?-v:v);return s} | |
document.getElementById( "ret" ).innerHTML = [myFunction("mcmlxxxvi"), myFunction("MIM"), myFunction("foobarbaz")] | |
</script> |
/* | |
Alternative version | |
--- | |
Use this only when string consists *only* from chars: | |
I, V, X, L, C, D, M, | |
i, v, x, l, c, d, m | |
Anything other will return complete trash | |
*/ | |
function(a){for(var v,s=0,i=a.length;i--;s+=v-(v=[1e3,,5,1,10,100,500,50][1.1*parseInt(a.charAt(i),36)&7])>0?-v:v);return s} |
Made it smaller:
function(a,v,s){for(s=0,i=a.length;i--;s+=v>(v=[100,500,,,,,1,,,50,1e3,,,,,,,,,5,,10][parseInt(a[i],36)-12])?-v:v);return s}
@williammalo, thanks!
I'd rather avoid using string numeric keys due to old IE, while var → argumets is a great advice
@williammalo Oh... In your version i
leaks into outer scope
@subzey
Oh noes!
@tsaniel, very nice suggestion, thanks! I'll update the code.