Skip to content

Instantly share code, notes, and snippets.

@andrewgunn
Created July 26, 2016 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewgunn/cd3c208eb84f8536788f07ca0e10116a to your computer and use it in GitHub Desktop.
Save andrewgunn/cd3c208eb84f8536788f07ca0e10116a to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
public class CharComparer : IEqualityComparer<char>
{
public bool Equals(char c1, char c2)
{
return char.ToLowerInvariant(c1) == char.ToLowerInvariant(c2);
}
public int GetHashCode(char c1)
{
return char.ToLowerInvariant(c1)
.GetHashCode();
}
}
public class RomanNumeralsParser
{
public RomanNumeralsParser()
{
_lookup = new Dictionary<char, int>(new CharComparer()) { { 'I', 1 }, { 'V', 5 }, { 'X', 10 }, { 'L', 50 }, { 'C', 100 }, { 'D', 500 }, { 'M', 1000 } };
}
private static bool IsValidValuePair(int currentValue, int previousValue)
{
if (currentValue >= previousValue)
{
return true;
}
return currentValue * 5 == previousValue || currentValue * 10 == previousValue;
}
public int Parse(string romanNumerals)
{
if (string.IsNullOrWhiteSpace(romanNumerals))
{
throw new ItsAllGreekToMeException(romanNumerals);
}
var parsedValue = 0;
var previousValue = 0;
var highestValue = 0;
foreach (var romanNumeral in romanNumerals.Reverse())
{
if (!_lookup.ContainsKey(romanNumeral))
{
throw new ItsAllGreekToMeException(romanNumerals);
}
var currentValue = _lookup[romanNumeral];
if (!IsValidValuePair(currentValue, previousValue))
{
throw new ItsAllGreekToMeException(romanNumerals);
}
if (currentValue < highestValue)
{
// VIX
// C = 0 10 1 5
// H = 0 0 0 10
// P = 0 0 10 1
throw new ItsAllGreekToMeException(romanNumerals);
}
if (previousValue > currentValue)
{
// IV = 5 - 1 = 4
parsedValue -= currentValue;
}
else
{
// II = 1 + 1 = 2
parsedValue += currentValue;
}
highestValue = previousValue > highestValue ? previousValue : highestValue;
previousValue = currentValue;
}
return parsedValue;
}
private readonly IDictionary<char, int> _lookup;
}
public class ItsAllGreekToMeException : Exception
{
public ItsAllGreekToMeException(string romanNumeral)
{
_romanNumeral = romanNumeral;
}
public string RomanNumeral
{
get
{
return _romanNumeral;
}
}
private readonly string _romanNumeral;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment