for index in str.indices {
...
str.remove(at: charIndex)
Недопустимо изменять строку во время ее итерации. str.indices
извлекается здесь один раз и становится недействительным после того, как вы изменили основную строку.
Я уверен, что будет много реализаций этого, потому что это небольшая, забавная проблема, которая привлекает реализации. Так почему не? Это просто крик рекурсии для меня.
let romanDigits: [Substring: Int] = ["I" : 1,
"V" : 5,
"X" : 10,
"L" : 50,
"C" : 100,
"D" : 500,
"M" : 1000]
let romanSums: [Substring: Int] = ["IV" : 4,
"IX" : 9,
"XL" : 40,
"XC" : 90,
"CD" : 400,
"CM" : 900]
func romanToInt<S: StringProtocol>(_ s: S) -> Int
where S.SubSequence == Substring {
if s.isEmpty { return 0 }
if let value = romanSums[s.prefix(2)] {
return value + romanToInt(s.dropFirst(2))
} else if let value = romanDigits[s.prefix(1)] {
return value + romanToInt(s.dropFirst(1))
} else {
fatalError("Invalid string")
}
}
let check = romanToInt("MCMXCIV")
Конечно, это на самом деле не проверяет правильность последовательностей, так что это своего рода мусор. «IIIIXXIII» - своего рода бред, но это работает. Но это соответствует первоначальному подходу.