I\'m trying to write a function that converts numbers to roman numerals. This is my code so far; however, it only works with numbers that are less than 400. Is there a quick
This is actually quite a fun problem, and based on the reverse example on dofactory.com (turning roman numerals to decimals) its quite easy to reverse the pattern, and perhaps improve it a little. This code will support numbers from 1 to 3999999.
Begin with a context class, this defines the I/O of the parser
public class Context
{
private int _input;
private string _output;
public Context(int input)
{
this._input = input;
}
public int Input
{
get { return _input; }
set { _input = value; }
}
public string Output
{
get { return _output; }
set { _output = value; }
}
}
And an abstract expression, which defines the parsing operation
public abstract class Expression
{
public abstract void Interpret(Context value);
}
Now, you need an abstract terminal expression, which defines the actual operation that will be performed:
public abstract class TerminalExpression : Expression
{
public override void Interpret(Context value)
{
while (value.Input - 9 * Multiplier() >= 0)
{
value.Output += Nine();
value.Input -= 9 * Multiplier();
}
while (value.Input - 5 * Multiplier() >= 0)
{
value.Output += Five();
value.Input -= 5 * Multiplier();
}
while (value.Input - 4 * Multiplier() >= 0)
{
value.Output += Four();
value.Input -= 4 * Multiplier();
}
while (value.Input - Multiplier() >= 0)
{
value.Output += One();
value.Input -= Multiplier();
}
}
public abstract string One();
public abstract string Four();
public abstract string Five();
public abstract string Nine();
public abstract int Multiplier();
}
Then, classes which define the behaviour of roman numerals (note, ive used the convention of lowercase where roman numerals use a bar over the letter to denote 1000 times)
class MillionExpression : TerminalExpression
{
public override string One() { return "m"; }
public override string Four() { return ""; }
public override string Five() { return ""; }
public override string Nine() { return ""; }
public override int Multiplier() { return 1000000; }
}
class HundredThousandExpression : TerminalExpression
{
public override string One() { return "c"; }
public override string Four() { return "cd"; }
public override string Five() { return "d"; }
public override string Nine() { return "cm"; }
public override int Multiplier() { return 100000; }
}
class ThousandExpression : TerminalExpression
{
public override string One() { return "M"; }
public override string Four() { return "Mv"; }
public override string Five() { return "v"; }
public override string Nine() { return "Mx"; }
public override int Multiplier() { return 1000; }
}
class HundredExpression : TerminalExpression
{
public override string One() { return "C"; }
public override string Four() { return "CD"; }
public override string Five() { return "D"; }
public override string Nine() { return "CM"; }
public override int Multiplier() { return 100; }
}
class TenExpression : TerminalExpression
{
public override string One() { return "X"; }
public override string Four() { return "XL"; }
public override string Five() { return "L"; }
public override string Nine() { return "XC"; }
public override int Multiplier() { return 10; }
}
class OneExpression : TerminalExpression
{
public override string One() { return "I"; }
public override string Four() { return "IV"; }
public override string Five() { return "V"; }
public override string Nine() { return "IX"; }
public override int Multiplier() { return 1; }
}
Almost there, we need a Non-terminal expression which contains the parse tree:
public class DecimalToRomaNumeralParser : Expression
{
private List expressionTree = new List()
{
new MillionExpression(),
new HundredThousandExpression(),
new TenThousandExpression(),
new ThousandExpression(),
new HundredExpression(),
new TenExpression(),
new OneExpression()
};
public override void Interpret(Context value)
{
foreach (Expression exp in expressionTree)
{
exp.Interpret(value);
}
}
}
Lastly, the client code:
Context ctx = new Context(123);
var parser = new DecimalToRomaNumeralParser();
parser.Interpret(ctx);
Console.WriteLine(ctx.Output); // Outputs CXXIII
Live example: http://rextester.com/rundotnet?code=JJBYW89744