|
I never enter a contest without knowing the prize, for tax purposes, but also in this case, it could be a job at CP... 
|
|
|
|
|
Actually it's a personality test to see who among you are worthy of being labelled a Brogrammer.
cheers,
Chris Maunder
The Code Project | Co-founder
Microsoft C++ MVP
|
|
|
|
|
You may want to snag CodeBroject.com just in case (CodePreject.com too).
|
|
|
|
|
 as a nerd, i can't resist... between, it's only a quick n' dirty solution:
public static int RomanToArabic(string romans) {
if (string.IsNullOrWhiteSpace(romans))
{
return 0;
}
romans = romans.Replace(" ", string.Empty);
if (!Regex.IsMatch(romans, "(I|V|X|C|M|D|L)+"))
{
throw new ArgumentException("Invalid numeral!!");
}
string invalidSequences = "(XXXX+)|(IIII+)|(CCCC+)|(MMMM+)|(DD+)|(LL+)|(VV+)";
if (Regex.IsMatch(romans, invalidSequences))
{
throw new ArgumentException("Invalid sequence!!");
}
int result = 0;
result += Regex.Matches(romans, "IV").Count * 4;
romans = Regex.Replace(romans, "IV", string.Empty);
result += Regex.Matches(romans, "IX").Count * 9;
romans = Regex.Replace(romans, "IX", string.Empty);
result += Regex.Matches(romans, "XL").Count * 40;
romans = Regex.Replace(romans, "XL", string.Empty);
result += Regex.Matches(romans, "XC").Count * 90;
romans = Regex.Replace(romans, "XC", string.Empty);
result += Regex.Matches(romans, "CD").Count * 400;
romans = Regex.Replace(romans, "CD", string.Empty);
result += Regex.Matches(romans, "CM").Count * 900;
romans = Regex.Replace(romans, "CM", string.Empty);
result += romans.Count(x => x == 'I');
romans = romans.Replace("I", string.Empty);
result += romans.Count(x => x == 'V') * 5;
romans = romans.Replace("V", string.Empty);
result += romans.Count(x => x == 'X') * 10;
romans = romans.Replace("X", string.Empty);
result += romans.Count(x => x == 'L') * 50;
romans = romans.Replace("L", string.Empty);
result += romans.Count(x => x == 'C') * 100;
romans = romans.Replace("C", string.Empty);
result += romans.Count(x => x == 'D') * 500;
romans = romans.Replace("D", string.Empty);
result += romans.Count(x => x == 'M') * 1000;
romans = romans.Replace("M", string.Empty);
if (romans != string.Empty)
{
throw new Exception("leftovers: " + romans);
}
return result;
}
i've tested it like this:
static void Main(string[] args) {
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 10000; i++)
{
RomanToArabic("MMVI");
RomanToArabic("MCMIII");
RomanToArabic("MCMXCIX");
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadKey();
}
and it take 1 second to execute, i feel a bad programmer
I'm brazilian and english (well, human languages in general) aren't my best skill, so, sorry by my english. (if you want we can speak in C# or VB.Net =p)
|
|
|
|
|
Chris Maunder wrote: Roman numerals to Arabic numbers
totally read this backward... at least now I have a solution for Arabic to Roman Numerals
Be The Noise
|
|
|
|
|
import sys
I=1
V=5
X=10
L=50
C=100
D=500
M=1000
a=0
b=0
c=0
for d in map(eval,sys.argv[1]):
if d > a:
b += d - c
c = 0
else:
b += c
c = d
a = d
print b + c
|
|
|
|
|
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 i<len(values)-1:
if values[i]<values[i+1]:
values[i]=-values[i]
return sum(values)
also, 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
Φευ! Εδόμεθα υπό ρηννοσχήμων λύκων!
(Alas! We're devoured by lamb-guised wolves!)
|
|
|
|
|
private int ToInt(string rom)
{
int length = rom.Length;
int result = 0;
for(int loop1=0; loop1 < length; loop1++)
{
char current = rom[loop1];
char next = loop1 < length - 1 ? rom[loop1 + 1] : ' ';
switch(current)
{
case 'I':
result += next == 'V' || next == 'X' ? -1 : 1;
break;
case 'V':
result += 5;
break;
case 'X':
result += next == 'L' || next == 'C' ? -10 : 10;
break;
case 'L':
result += 50;
break;
case 'C':
result += next == 'D' || next == 'M' ? -100 : 100;
break;
case 'D':
result += 500;
break;
case 'M':
result += 1000;
break;
}
}
return result;
}
|
|
|
|
|
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 (prevDigit<digit) val-=2*prevDigit;
val+=prevDigit;
prevDigit=digit;
}
val+=prevDigit;
return true;
}
BTW: is it Friday already?
|
|
|
|
|
This is definitely better than my attempt.
|
|
|
|
|
I'm unsure when I wrote this, but it must have been the 90s, in VAX C or DEC C. I'm shocked (shocked! I say) at the inconsistent braces.
size_t
roman2dec
(
char *subject
)
{
size_t result = 0 , current , high = 0 ;
int index ;
for ( index = strlen(subject)-1 ; index >= 0 ; index-- ) {
switch ( (char) *(subject + index) )
{
case 'I' :
case 'i' : current = 1 ; break ;
case 'V' :
case 'v' : current = 5 ; break ;
case 'X' :
case 'x' : current = 10 ; break ;
case 'L' :
case 'l' : current = 50 ; break ;
case 'C' :
case 'c' : current = 100 ; break ;
case 'D' :
case 'd' : current = 500 ; break ;
case 'M' :
case 'm' : current = 1000 ; break ;
default : current = 0 ; break ;
}
if ( current < high )
result -= current ;
else
{
result += current ;
high = current ;
}
}
return ( result ) ;
}
|
|
|
|
|
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 '?').
function RtoA(r)
{
var Rch =
{
I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000,
CM: -100, CD: -100, XC: -10, XL: -10, IX: -1, IV: -1
};
var R = r.toUpperCase();
var A = 0;
for (var i = 0; i < R.length; i++)
{
var ch = R.charAt(i);
A +=
Rch[ch + (R.charAt(i + 1) || '?')]
|| Rch[ch]
|| 0;
};
return A;
}
alert(RtoA('MDC'));
alert(RtoA('mcmxcix'));
modified 10-May-12 6:35am.
|
|
|
|
|
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.
|
|
|
|
|
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"));
Console.WriteLine(RomanToArabic("mcmxcix"));
Console.ReadKey();
}
}
}
modified 10-May-12 8:29am.
|
|
|
|
|
Nice. I like the % ' ' bits, and appreciate you used literal VII .
|
|
|
|
|
oops I removed the % ' ' ...
Ok I put back a:
"ivxlcdm".IndexOf((char)(c | ' '))
|
|
|
|
|
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);
}
|
|
|
|
|
Geez, I thought it was going to be something hard.
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
|
|
|
|
|
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)
}
|
|
|
|
|
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(f<p,-f,f)
if(f>p,p:=f,)
b--
END
RETURN r
Compiles with xHarbour.
|
|
|
|
|
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();
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++)
{
int nextVal;
int currentVal = Convert.ToInt32(ht[RomanNumber[index]]);
if (index + 1 < RomanNumber.Length)
{
nextVal = Convert.ToInt32(ht[RomanNumber[index + 1]]);
}
else
{
nextVal = 0;
}
if (nextVal > currentVal)
{
currentVal = nextVal - currentVal;
index++;
}
value += currentVal;
}
label1.Text = value.ToString();
}
}
}
|
|
|
|
|
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
|
|
|
|
|