Нет ничего плохого в ответе Давида Пастора, но мне действительно нравятся необдуманные мысли Βασίλης Δ.Это просто кажется очень естественным подходом.Поэтому я хотел бы свести их воедино.
Во-первых, начиная с кода Βασίλης Δ., Добавляя псевдоним intValue
только потому, что я думаю, что он читается немного лучше.
enum Roman: Int {
case I = 1
case V = 5
case X = 10
case L = 50
case C = 100
case D = 500
case M = 1000
var intValue: Int { return rawValue }
}
Затем предоставьте поиск для строк, используя новый CaseIterable:
extension Roman: CaseIterable {
enum Error: Swift.Error {
case invalid
}
init<S: StringProtocol>(_ string: S) throws {
guard let roman = Roman.allCases.first(where: { "\($0)" == string }) else {
throw Error.invalid
}
self = roman
}
init(_ character: Character) throws { try self.init(String(character)) }
}
. С этим, я думаю, алгоритм number
становится немного лучше в верхней части:
let number = try "XXI".reversed()
.map { try Roman($0).intValue }
.reduce((total: 0, max: 0)) { result, value in
let newTotal = result.total + (value < result.max ? -value : value)
return (newTotal, max(result.max, value))
}.total
Я не большой поклонник этого алгоритма, потому что он некорректно работает при неправильном вводе, но по крайней мере эта версия отклоняет недопустимые символы, а не конвертирует их в 0.