Все, что вам нужно, - это перебрать ваши символы строки в обратном порядке и сопоставить эти значения символов. Начните с maxValue равным нулю, переключите значение букв, сохраните его как maxValue, и если значение равно maxValue, добавьте его, иначе вычтите фактическое значение. Вы также можете использовать regex (строгий или нет) для проверки и выдачи ошибки в случае ее отказа. Попробуйте вот так:
Xcode 9.x • Swift 4.x
Примечание: для версии Swift 3 или ранее проверьте историю изменений.
extension String {
enum RomanParsingError: Error {
case invalidNumber
}
func romanNumeralValue() throws -> Int {
guard range(of: "^(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$", options: .regularExpression) != nil else {
throw RomanParsingError.invalidNumber
}
var result = 0
var maxValue = 0
uppercased().reversed().forEach {
let value: Int
switch $0 {
case "M":
value = 1000
case "D":
value = 500
case "C":
value = 100
case "L":
value = 50
case "X":
value = 10
case "V":
value = 5
case "I":
value = 1
default:
value = 0
}
maxValue = max(value, maxValue)
result += value == maxValue ? value : -value
}
return result
}
}
использование:
do {
let decimal = try "MCMLXXVIII".romanNumeralValue()
print(decimal) // 1978
} catch {
print(error)
}
do {
let decimal = try "IIIV".romanNumeralValue()
print(decimal)
} catch {
print(error) // "invalidNumber\n"
}