• Category: behavioral
  • Type: class
  • Motivation: build an interpreter to solve the problem by Interpreting those sentences in a simple language

diagram

do {
    let client = RomanNumeral()
    let result: Int = client.convert("XIV");
    print(result) // 14
}
// client
public struct RomanNumeral
{
    public func convert(_ numeral: String) -> Int
    {
        parse(numeral)
            .map { $0.interpret() }
            .reduce(0) { $0 + $1 }
    }

    private func parse(_ numeral: String) -> [Expression]
    {
        var exps: [Expression] = []
        var terms: [TermExpression] = numeral.map{ TermExpression(symbol: $0) }
        while !terms.isEmpty {
            let expression = terms.removeFirst()
            let shouldShift = terms.count == 1 ||
                (terms.count > 1 && terms[0].interpret() > terms[1].interpret())
            if shouldShift {
                let cal = CalExpression(lhs: expression, rhs: terms.removeFirst())
                exps.append(cal)
            } else {
                exps.append(expression)
            }
        }
        return exps
    }
}
protocol Expression
{
    func interpret() -> Int
}

struct TermExpression: Expression
{
    let symbol: Character

    func interpret() -> Int {
        switch symbol {
        case "I": return 1
        case "V": return 5
        case "X": return 10
        case "L": return 50
        case "C": return 100
        case "D": return 500
        case "M": return 1_000
        default:return 0
        }
    }
}

struct CalExpression: Expression
{
    let lhs: Expression
    let rhs: Expression

    func interpret() -> Int {
        if lhs.interpret() < rhs.interpret() {
            return rhs.interpret() - lhs.interpret()
        } else {
            return rhs.interpret() + lhs.interpret()
        }
    }
}