private static Exception?CheckRepeatedDigits(string roman, RomanizerOptions options) { var allowFourSum = options.HasFlag(RomanizerOptions.ALLOW_FOUR_SEQUENTIAL_DIGITS); var allowMultipleSum = options.HasFlag(RomanizerOptions.ALLOW_MULTIPLE_SEQUENTIAL_DIGITS); for (var i = 0; i < roman.Length; i++) { var current = roman[i]; var totalRepeated = (byte)roman.Skip(i).TakeWhile(digit => digit == current).Count(); switch (totalRepeated) { case <= 3: continue; case 4 when !allowFourSum: return(new ArithmeticAdditionException( roman, current, totalRepeated, $"Roman number '{roman}' with multiple repeated digits of '{current}' with total '{totalRepeated}', so it is invalid roman number. If you want sum 4 digits you need allow this in options entry.")); case > 4 when !allowMultipleSum: return(new ArithmeticAdditionException( roman, current, totalRepeated, $"Roman number '{roman}' with multiple repeated digits of '{current}' with total '{totalRepeated}', so it is invalid roman number. If you want sum more than 4 digits you need allow this in options entry.")); } } return(null); }
internal static string RomanizeUnsafe(ushort number, RomanizerOptions options = RomanizerOptions.DEFAULT_STRICT) { StringBuilder roman = new(MAX_VALUE_ROMAN.Length); do { for (var i = 0; i < romanNumbersReversed.Count(); i++) { var(romanDigit, decimalDigit) = romanNumbersReversed.ElementAt(i); if (number < decimalDigit) { continue; } var count = (ushort)Math.Round((double)(number / decimalDigit)); /* * Special rule * * When the number have free 4 units, need subtract then by higher value for not throw 4 sum limit. * * Example: IIII => IV */ var isSpecialCountRule = count == 4 && !options.HasFlag(RomanizerOptions.ALLOW_FOUR_SEQUENTIAL_DIGITS); if (isSpecialCountRule) { var higherValueIndex = i - 1; var(rightRomanDigit, rightDigit) = romanNumbersReversed.ElementAtOrDefault(higherValueIndex); var existRightValue = rightRomanDigit != 0 && rightDigit > 0; /* * Need check if have higher value to subtract free units */ if (existRightValue) { roman.Append(romanDigit); roman.Append(rightRomanDigit); number -= (ushort)(decimalDigit * count); break; } } /* * Special rule end */ for (var j = 0; j < count; j++) { roman.Append(romanDigit); } number -= (ushort)(decimalDigit * count); break; } } while (number > 0); return(roman.ToString()); }
private static void CheckSpecialRules(char left, char right, char current, int rightValue, RomanizerOptions options) { var isNotStrict = !options.HasFlag(RomanizerOptions.DEFAULT_STRICT); if (isNotStrict) { return; } var isAddition = Util.ConvertSingleRomanToDecimal(current) >= rightValue; if (isAddition) { CheckAdditionSpecialRules(current, rightValue, options); } else { CheckSubtractionSpecialRules(left, right, current, options); } }