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 (var arabicNumeral in Enumerable.Range(1, DICTIONARY_PREPOPULATION_SIZE + 1)) { GenerateRomanNumerals(arabicNumeral, out var romanNumeralAsString, out var arabicNumeralAsString); var arm = new ArabicRomanNumeral(arabicNumeral, arabicNumeralAsString, romanNumeralAsString); _arabicRomanNumeralsMapping.Add(arm); var sam = new SimpleArabicNumeral(arabicNumeral); var srm = new SimpleRomanNumeral(romanNumeralAsString); _simpleArabicNumeralMappings.Add(sam, srm); } } private static void GenerateRomanNumerals(int arabicNumeral, out string romanNumeral, out string arabicNumeralAsString) { var romanNumeralObject = new RomanNumeral(arabicNumeral); romanNumeral = romanNumeralObject.ToRomanNumeral(); arabicNumeralAsString = Convert.ToString(arabicNumeral); } private static HashSet GenerateAdditionalMappings(int offset, int length) { var additionalArabicRomanNumerals = new HashSet(); foreach (var arabicNumeral in Enumerable.Range(offset, length)) { GenerateRomanNumerals(arabicNumeral, out var romanNumeral, out var arabicNumeralAsString); var 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)); } var 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) { var moreNumerals = new Dictionary(); foreach (var arabicNumeral in Enumerable.Range(offset, length)) { GenerateRomanNumerals(arabicNumeral, out var romanNumeral, out _); var san = new SimpleArabicNumeral(arabicNumeral); var srn = new SimpleRomanNumeral(romanNumeral); moreNumerals.Add(san, srn); } return moreNumerals; } } }