Last active
August 1, 2024 08:25
-
-
Save andrewgunn/cd3c208eb84f8536788f07ca0e10116a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 = Math.Max(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