Coding Challenge Of The Day
-
I once met a well formed roman, when I was touring through Italy. :cool:
Chris Meech I am Canadian. [heard in a local bar] In theory there is no difference between theory and practice. In practice there is. [Yogi Berra] posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
did you get here number?
-
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
Apologies if other respondents have used a similar technique, but I have deliberately not looked at the other replies before attempting this challenge so that I am not influenced by other people's ideas. The following is in JavaScript, not obfuscated. The tricks are: Using an object literal as a lookup table and treating the double chars as subtractors from the second single chars (e.g. CM = [CM] + [M] = -100 + 1000 = 900). The only awkward part is preventing the last char being counted twice - once as a single char and once as a double char with no second char (this is done by appending '?').
// Roman to Arabic character translations
function RtoA(r) // r is roman numerals in any case
{
// Roman to Arabic conversion table
var Rch =
{
// Single chars: Add each value separately to the total
I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000,
// Double chars: Modify the sum of the second char as subtractors
CM: -100, CD: -100, XC: -10, XL: -10, IX: -1, IV: -1
};var R = r.toUpperCase(); // Ignore case var A = 0; // Arabic equivalent // Parse the text converting valid single chars and double chars // Set any invalid single or double char combinations as translating to zero for (var i = 0; i < R.length; i++) { var ch = R.charAt(i); A += Rch\[ch + (R.charAt(i + 1) || '?')\] // Double char conversion || Rch\[ch\] // Single char conversion || 0; // No conversion - invalid char }; // for return A;
}
alert(RtoA('MDC')); // 1600
alert(RtoA('mcmxcix')); // 1999 -
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
First time post so hope this looks OK; 1 CRT "NUMERALS: ": ; INPUT NUM 2 CRT "NUMBER : ":ICONV(NUM, 'NR') 3 END Written in UniVerse BASIC.
-
Or, somewhat more tersely,
def r2d3(r,(s,M,C,X,I,z,V,L,D)=["%%s%d"%v for v in[1001,1000,100,10,1,0,5,50,500]]):
return eval("".join([
p%"+-"[eval( p%"%s>"%d%"")]
for d,p in zip(map(eval,'%sz'%r),map(eval,'s%s'%r))
][1:]))Or, somewhere in between:
def a6(roman):
if len(roman)==0:
return 0
mapping={"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000}
values=[mapping[digit] for digit in roman.upper()]
for i in range(len(values)):
if ialso, added capitalization tolerance, so that "MCM" and "mcm" evaluate the same. I haven't added a check that the argument is a valid roman numeral, but that is left as an exercise to the reader ;P
Φευ! Εδόμεθα υπό ρηννοσχήμων λύκων!
(Alas! We're devoured by lamb-guised wolves!) -
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
I hope it will be obscure enough. ;)
class Program
class Program
{
static int RomanToArabic(string r)
{
int x, y, z = x = y = 0;
foreach (char c in r)
y += ((z = (int)Math.Pow(10, (z = "ivxlcdm".IndexOf((char)(c | ' '))) / 2) * (1 + 4 * (z & 1))) > x ? -2 * x + (x = z) : x = z);
return y;
}static void Main(string\[\] args) { Console.WriteLine(RomanToArabic("MDC")); // 1600 Console.WriteLine(RomanToArabic("mcmxcix")); // 1999 Console.ReadKey(); } }
}
-
no arrays, no dictionaries, no obscure language, just some original coding:
public static bool TryParseRoman(string wellFormedRoman, out int val) {
val=0;
int prevDigit=0;
foreach (char c in wellFormedRoman) {
int index="IVXLCDM".IndexOf(c);
if (index<0) {val=0; return false;}
int digit=1;
int factor=5;
while (--index>=0) { digit*=factor; factor=7-factor; }
if (prevDigitBTW: is it Friday already?
:)
Luc Pattyn [My Articles] Nil Volentibus Arduum
This is definitely better than my attempt.
-
I hope it will be obscure enough. ;)
class Program
class Program
{
static int RomanToArabic(string r)
{
int x, y, z = x = y = 0;
foreach (char c in r)
y += ((z = (int)Math.Pow(10, (z = "ivxlcdm".IndexOf((char)(c | ' '))) / 2) * (1 + 4 * (z & 1))) > x ? -2 * x + (x = z) : x = z);
return y;
}static void Main(string\[\] args) { Console.WriteLine(RomanToArabic("MDC")); // 1600 Console.WriteLine(RomanToArabic("mcmxcix")); // 1999 Console.ReadKey(); } }
}
Nice. I like the
% ' '
bits, and appreciate you used literalVII
. :)Luc Pattyn [My Articles] Nil Volentibus Arduum
-
Nice. I like the
% ' '
bits, and appreciate you used literalVII
. :)Luc Pattyn [My Articles] Nil Volentibus Arduum
oops I removed the
% ' '
... Ok I put back a:"ivxlcdm".IndexOf((char)(c | ' '))
-
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
This is my final answer
static int RomanToArabic(string roman, int x = 0, int y=0)
{
return roman.Length == 0 ? 0 : (y = (int)Math.Pow(10, (y = "ivxlcdm".IndexOf((char)(roman[0] | ' '))) / 2) * (1 + 4 * (y & 1))) + (y > x ? -2 * x : 0) + RomanToArabic(roman.Substring(1), y);
} -
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
Geez, I thought it was going to be something hard.
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
-
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
OK, I admit it isn't very small. Scala is number 46 on the Tiobe Index this month, so perhaps it is obscure enough to qualify. Being a "functional" language there are actually 3 functions but I nested them in one.
def convertRomanToArabic(romanNumeral: String): Int = { var previous = 0 def convertSingleRomanNumeral(numeral: Char): Int = { numeral match { case 'I' => 1 case 'V' => 5 case 'X' => 10 case 'L' => 50 case 'C' => 100 case 'D' => 500 case 'M' => 1000 } } def addRomans(next: Int, accumulator: Int): Int = { if (previous == 0) previous = accumulator var addto = if (previous > next) next \* -1 else next previous = next accumulator + addto } val values = romanNumeral.toList.map(n => convertSingleRomanNumeral(n)) values.reduceRight(addRomans) }
-
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
FUNCTION Roman2Dec(cRoman)
LOCAL nPointer := len(cRoman) LOCAL nPos := 0,nFaceVal := 0,nLastVal := 0, nReturn := 0 WHILE nPointer > 0 nPos := at(substr(cRoman, nPointer, 1),'IVXLCDM') -1 nFaceVal := (10 ^ int((nPos)/2)) \* (1+((nPos) % 2 \* 4)) nReturn += iif(nFaceVal < nLastVal, -nFaceVal, nFaceVal) IF nFaceVal > nLastVal nLastVal := nFaceVal ENDIF nPointer-- ENDDO
RETURN nReturn
-
for well-formed roman numerals, modern rules:
int r2d2(const char *r)
{
int val[128];
memset(val,0,sizeof(int)*128);
val['I']=1; val['V']=5;
val['X']=10; val['L']=50;
val['C']=100; val['D']=500; val['M']=1000;int a = 0;
for (int cv, pv = 0, i=strlen(r)-1;i>=0;i--)
{
cv = val[r[i]];
a += cv * (pv > cv ? -1 : 1);
pv = cv;
}return a;
}
These aren't the roman numerals you're looking for. You should go about your business. Move along move along.
ragnaroknrol: Yes, but comparing a rabid wolverine gnawing on your face while stabbing you with a fountain pen to Vista is likely to make the wolverine look good, so it isn't exactly that big of a compliment.
-
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
In C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace RomanNumerConverter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}private void button1\_Click(object sender, EventArgs e) { Hashtable ht = new Hashtable(); // Create a look-up table to look up Roman numerals and get there associated values. ht.Add('M', 1000); ht.Add('D', 500); ht.Add('C', 100); ht.Add('L', 50); ht.Add('X', 10); ht.Add('V', 5); ht.Add('I', 1); String RomanNumber = textBox1.Text; int value = 0; for (int index = 0; index < RomanNumber.Length; index++) // Go through the entered Roman numeral a character at a time { int nextVal; int currentVal = Convert.ToInt32(ht\[RomanNumber\[index\]\]); // Get the value of the current character. if (index + 1 < RomanNumber.Length) // if you are not at the end of the string { nextVal = Convert.ToInt32(ht\[RomanNumber\[index + 1\]\]);// Peek at the next number to see you need to use it to combine characters for a single value(e.g. IV equates to 4) } else { nextVal = 0; // No more characters so just set this to 0 to simplfy the algorithm. } if (nextVal > currentVal)// If the value of nextVal is greater than currentVal, we have a subtractive situation (e.g. IV) { currentVal = nextVal - currentVal; // To determine the value you have to subtract the value of the first number of the pair from the second number(e.g. IV = 5 - 1 = 4) index++;// Used nextVal to help determine the number so increment the index to skip over that character in the next iteration. } value += currentVal; // Add the values of the Roman numerals up. } label1.Text = value.ToString(); //Convert the sum to string to use as a text label. This is the converted number in Arabic numerals. } }
}
-
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
Hideous C# one-liner* with whitespace added to ahahahaha enhance readability.
static double RomanToInt( string roman ) {
return (
Enumerable.Range( 0, 3 )
.Select(
i =>
( i + 1 ) * 2 - 2
)
.Aggregate(
roman.ToLower(),
( current, i ) =>
current
.Replace(
"ivxlcdm".Substring( i, 2 ),
new string( "ivxlcdm"[ i ], 4 )
)
.Replace(
"ivxlcdm"[ i ].ToString() + "ivxlcdm"[ i + 2 ].ToString(),
"ivxlcdm"[ i + 1 ].ToString() + new string( "ivxlcdm"[ i ], 4 )
)
)
.Select(
i =>
"ivxlcdm".IndexOf( i )
)
.Select(
x =>
x % 2 == 0 ?
Math.Pow( 10, x / 2 ) :
Math.Pow( 10, ( x + 1 ) / 2 ) / 2
)
.Sum()
);
}*Not counting the function declaration - trivial to convert to a true a one-liner but you asked for a function
-
Hideous C# one-liner* with whitespace added to ahahahaha enhance readability.
static double RomanToInt( string roman ) {
return (
Enumerable.Range( 0, 3 )
.Select(
i =>
( i + 1 ) * 2 - 2
)
.Aggregate(
roman.ToLower(),
( current, i ) =>
current
.Replace(
"ivxlcdm".Substring( i, 2 ),
new string( "ivxlcdm"[ i ], 4 )
)
.Replace(
"ivxlcdm"[ i ].ToString() + "ivxlcdm"[ i + 2 ].ToString(),
"ivxlcdm"[ i + 1 ].ToString() + new string( "ivxlcdm"[ i ], 4 )
)
)
.Select(
i =>
"ivxlcdm".IndexOf( i )
)
.Select(
x =>
x % 2 == 0 ?
Math.Pow( 10, x / 2 ) :
Math.Pow( 10, ( x + 1 ) / 2 ) / 2
)
.Sum()
);
}*Not counting the function declaration - trivial to convert to a true a one-liner but you asked for a function
Sweet.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
-
Sweet.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
Better:
static int RomanToInt( string roman ) {
return roman
.ToLower()
.Select(
n =>
new Dictionary {
{'i', 1},
{'v', 5},
{'x', 10},
{'l', 50},
{'c', 100},
{'d', 500},
{'m', 1000},
}[ n ]
)
.Aggregate(
new[] {0, 0, 0},
( c, d ) =>
new[] {
c[ 0 ] + ( d > c[ 2 ] ? d - c[ 1 ] : c[ 1 ] ),
d > c[ 2 ] ? 0 : d,
d
}
)
.Take( 2 )
.Sum();
} -
FUNCTION Roman2Dec(cRoman)
LOCAL nPointer := len(cRoman) LOCAL nPos := 0,nFaceVal := 0,nLastVal := 0, nReturn := 0 WHILE nPointer > 0 nPos := at(substr(cRoman, nPointer, 1),'IVXLCDM') -1 nFaceVal := (10 ^ int((nPos)/2)) \* (1+((nPos) % 2 \* 4)) nReturn += iif(nFaceVal < nLastVal, -nFaceVal, nFaceVal) IF nFaceVal > nLastVal nLastVal := nFaceVal ENDIF nPointer-- ENDDO
RETURN nReturn
My previous code after some Herbalife:-
FUNC rr(c)
r=0;p=0;b=len(c)
WHILE b>0
v=at(c[b],'IVXLCDM')-1
f=10^int(v/2)*(v%2*4+1)
r+=if(fp,p:=f,)
b--
END
RETURN rCompiles with xHarbour.
-
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
private Dictionary R2A_dictionary = new Dictionary()
{
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};private int ConvertRomanToArabic(string roman)
{
int result = 0;
int previous = Int32.MaxValue, current = 0;
for (int i = 0; i < roman.Length; i++)
{
current = R2A_dictionary[roman[i]];
result += current;
if (current > previous)
result -= previous << 1;
previous = current;
}
return result;
} -
Write a function to convert Roman numerals to Arabic numbers. The smaller the better. Bonus points, as always, for obscure languages and obfuscated assembler.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
If there are bonus points for using hated constructs, how about this one-liner using JavaScript's 'eval' function?
function RtoA(r)
{ return eval(r.toUpperCase()
.replace(/CM/g, '+900').replace(/CD/g, '+400').replace(/XC/g, '+90').replace(/XL/g, '+40')
.replace(/IX/g, '+9').replace(/M/g, '+1000').replace(/D/g, '+500').replace(/C/g, '+100')
.replace(/L/g, '+50').replace(/X/g, '+10').replace(/V/g, '+5').replace(/I/g, '+1'));
}or for obscure use of Regular Expression matching and using string length as scale factors:
function RtoA(r) // r is roman numerals in any case
{
var m = r.match(/^(M*)(CM)?(D)?(CD)?(C*)(XC)?(XL)?(L)?(X*)(IX)?(IV)?(V)?(I*)$/i);return ( m\[1\].length \* 1000 + // M m\[2\].length \* 450 + // CM m\[3\].length \* 500 + // D m\[4\].length \* 200 + // CD m\[5\].length \* 100 + // C m\[6\].length \* 45 + // XC m\[7\].length \* 25 + // XL m\[8\].length \* 50 + // L m\[9\].length \* 10 + // X m\[10\].length \* 4.5 + // IX m\[11\].length \* 2 + // IV m\[12\].length \* 5 + // V m\[13\].length // I );
} // RtoA
Of the three submissions that I have made, this is the only one that enforces the ordering of numerals (e.g. all Cs must be before all Is) and the fact that some character sequences can only appear once (e.g. D can only appear once, except when following CD which also can only appear once). The odd scale multiplier factors (e.g. 4.5) come from the fact that some letter combinations have 2 characters and the substring lengths are thus twice as long (IX = 2 chars = value of 9, so each char is worth 9 / 2 = 4.5).