swiftstringmathpostfix-operatornsexpression

NSExpresseion, determine operating from left-associative


func postFix(_ expr: String) -> Int {
    // write your code here
    let nums = expr.components(separatedBy:CharacterSet.decimalDigits.inverted)
        .joined()
    let set = CharacterSet(charactersIn: "+*/%-")
    var ch = expr.components(separatedBy: set.inverted).joined()
    ch.append(" ")
    var rslt = String()


    for i in 0..<nums.count {
        let index = str.index(str.startIndex, offsetBy: i)
        rslt.append(nums[index])
        rslt.append(ch[index])
    }
    let theSet = CharacterSet(charactersIn: "+*/%-0123456789")
    let final = rslt.components(separatedBy: theSet.inverted).joined()
    let expn = NSExpression(format: final)
    let chal = expn.expressionValue(with: nil, context: nil)

    return  chal as! Int
}
print(postFix("4 1 - 2 *"))

Im making a method to resolve a math operation from an unsorted string the only problem I'm facing is I couldn't determine operating from left-associative . instead of 4 - (1 * 2) = 2 I want it to start from left side and ignore whether to start with * or / first so (4 - 1 ) * 2 = 6


Solution

  • I would change your logic a bit. First get all numbers and all operators, then get the first element and use it as the lhs, iterate the numbers and the operators dropping the first number. Construct your expression using the lhs + the operator + the current number (rhs). assign the result to a var and the next lhs will be the result converted to string. Something like:


    func postFix(_ expr: String) -> Int {
        let numbers = expr.split(whereSeparator: {!"0123456789".contains($0)})
        let operators = expr.split(whereSeparator: {!"+*/%-".contains($0)} )
        guard var lhs = numbers.first else { return .zero }
        var result = 0
        for (rhs, oprtr) in zip(numbers.dropFirst(),operators)  {
            let format = String([lhs,rhs].joined(separator: " " + oprtr + " "))
            result = NSExpression(format: format)
                .expressionValue(with: nil, context: nil) as? Int ?? 0
            lhs = String(result)[...]
        }
        return  result
    }
    

    print(postFix("4 1 - 2 *"))  // "6\n"