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} |
Oh, noes! That breaks the validation so using "8C8LJJJVI"
yields same as "MCMLXXXVI
".
Guess, I should revert to the previous version as I already have x-alternative.js
in this gist that doesn't validate its input.
Completely forgot about the validation... anyway,
[100,500,,,,,1,,,50,1e3,,,,,,,,,5,,10]
is still 2 bytes shorter than {6:1,19:5,21:10,9:50,0:100,1:500,10:1e3}
I think that way, too. I just tried to “strip” some of those commas anyhow.
If you don't care for IE compatibility (or tell IE users to .split('') the input string before using the function), you can replace .charAt() with [], too.
Maybe save 2 bytes?
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}
@tsaniel, very nice suggestion, thanks! I'll update the code.
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!
You're welcome! And that's another really cool idea! Btw, you forgot to update test.html.