using System; using System.Collections.Generic; using System.Linq; namespace NzbDrone.Core.Parser.RomanNumerals { public static class RomanNumeralParser { private const int DICTIONARY_PREPOPULATION_SIZE = 20; private static HashSet _arabicRomanNumeralsMapping; private static Dictionary _simpleArabicNumeralMappings; static RomanNumeralParser() { PopluateDictionariesReasonablyLarge(); } private static void PopluateDictionariesReasonablyLarge() { if(_simpleArabicNumeralMappings != null || _arabicRomanNumeralsMapping != null) { return; } _arabicRomanNumeralsMapping = new HashSet(); _simpleArabicNumeralMappings = new Dictionary(); foreach (int arabicNumeral in Enumerable.Range(1,DICTIONARY_PREPOPULATION_SIZE +1)) { string romanNumeralAsString, arabicNumeralAsString; GenerateRomanNumerals(arabicNumeral, out romanNumeralAsString, out arabicNumeralAsString); ArabicRomanNumeral arm = new ArabicRomanNumeral(arabicNumeral, arabicNumeralAsString, romanNumeralAsString); _arabicRomanNumeralsMapping.Add(arm); SimpleArabicNumeral sam = new SimpleArabicNumeral(arabicNumeral); SimpleRomanNumeral srm = new SimpleRomanNumeral(romanNumeralAsString); _simpleArabicNumeralMappings.Add(sam, srm); } } private static void GenerateRomanNumerals(int arabicNumeral, out string romanNumeral, out string arabicNumeralAsString) { RomanNumeral romanNumeralObject = new RomanNumeral(arabicNumeral); romanNumeral = romanNumeralObject.ToRomanNumeral(); arabicNumeralAsString = Convert.ToString(arabicNumeral); } private static HashSet GenerateAdditionalMappings(int offset, int length) { HashSet additionalArabicRomanNumerals = new HashSet(); foreach (int arabicNumeral in Enumerable.Range(offset, length)) { string romanNumeral; string arabicNumeralAsString; GenerateRomanNumerals(arabicNumeral, out romanNumeral, out arabicNumeralAsString); ArabicRomanNumeral arm = new ArabicRomanNumeral(arabicNumeral, arabicNumeralAsString, romanNumeral); additionalArabicRomanNumerals.Add(arm); } return additionalArabicRomanNumerals; } public static HashSet GetArabicRomanNumeralsMapping(int upToArabicNumber = DICTIONARY_PREPOPULATION_SIZE) { if (upToArabicNumber == DICTIONARY_PREPOPULATION_SIZE) { return new HashSet(_arabicRomanNumeralsMapping.Take(upToArabicNumber)); } if (upToArabicNumber < DICTIONARY_PREPOPULATION_SIZE) { return (HashSet) new HashSet(_arabicRomanNumeralsMapping).Take(upToArabicNumber); } if (upToArabicNumber >= DICTIONARY_PREPOPULATION_SIZE) { if (_arabicRomanNumeralsMapping.Count >= upToArabicNumber) { return new HashSet(_arabicRomanNumeralsMapping.Take(upToArabicNumber)); } HashSet largerMapping = GenerateAdditionalMappings(DICTIONARY_PREPOPULATION_SIZE + 1, upToArabicNumber); _arabicRomanNumeralsMapping = (HashSet)_arabicRomanNumeralsMapping.Union(largerMapping); } return _arabicRomanNumeralsMapping; } public static Dictionary GetArabicRomanNumeralAsDictionary( int upToArabicNumer = DICTIONARY_PREPOPULATION_SIZE) { Func , int, Dictionary> take = (mapping, amountToTake) => new Dictionary( mapping.Take(amountToTake).ToDictionary(key => key.Key, value => value.Value)); if (upToArabicNumer == DICTIONARY_PREPOPULATION_SIZE) { return take(_simpleArabicNumeralMappings, upToArabicNumer); } if (upToArabicNumer > DICTIONARY_PREPOPULATION_SIZE) { if (_simpleArabicNumeralMappings.Count >= upToArabicNumer) { return take(_simpleArabicNumeralMappings, upToArabicNumer); } var moreSimpleNumerals = GenerateAdditionalSimpleNumerals(DICTIONARY_PREPOPULATION_SIZE, upToArabicNumer); _simpleArabicNumeralMappings = (Dictionary) _simpleArabicNumeralMappings.Union(moreSimpleNumerals); return take(_simpleArabicNumeralMappings, _arabicRomanNumeralsMapping.Count); } if (upToArabicNumer < DICTIONARY_PREPOPULATION_SIZE) { return take(_simpleArabicNumeralMappings, upToArabicNumer); } return _simpleArabicNumeralMappings; } private static Dictionary GenerateAdditionalSimpleNumerals(int offset, int length) { Dictionary moreNumerals = new Dictionary(); foreach (int arabicNumeral in Enumerable.Range(offset, length)) { string romanNumeral; string arabicNumeralAsString; GenerateRomanNumerals(arabicNumeral, out romanNumeral, out arabicNumeralAsString); SimpleArabicNumeral san = new SimpleArabicNumeral(arabicNumeral); SimpleRomanNumeral srn = new SimpleRomanNumeral(romanNumeral); moreNumerals.Add(san,srn); } return moreNumerals; } } }