import Foundation
class EnhancedCalculator {
func calculate(_ expression: String) -> Double {
let tokens = tokenize(expression)
let rpn = infixToPostfix(tokens)
return evaluateRPN(rpn)
}
private func tokenize(_ expression: String) -> [String] {
var tokens = [String]()
var number = ""
for char in expression {
if char.isWhitespace {
continue
} else if char.isNumber || char == "." {
number.append(char)
} else {
if !number.isEmpty {
tokens.append(number)
number = ""
}
tokens.append(String(char))
}
}
if !number.isEmpty {
tokens.append(number)
}
return tokens
}
private func infixToPostfix(_ tokens: [String]) -> [String] {
var output = [String]()
var operators = [String]()
let precedence: [String: Int] = [
"+": 1, "-": 1,
"*": 2, "/": 2,
"^": 3, "√": 3,
"(": 0, ")": 0
]
for token in tokens {
if let _ = Double(token) {
output.append(token)
} else if token == "(" {
operators.append(token)
} else if token == ")" {
while let top = operators.last, top != "(" {
output.append(operators.removeLast())
}
operators.removeLast()
} else {
while let top = operators.last, precedence[top]! >= precedence[token]! {
output.append(operators.removeLast())
}
operators.append(token)
}
}
while operators.last != nil {
output.append(operators.removeLast())
}
return output
}
private func evaluateRPN(_ tokens: [String]) -> Double {
var stack = [Double]()
for token in tokens {
if let value = Double(token) {
stack.append(value)
} else if token == "√" {
if let operand = stack.popLast() {
stack.append(sqrt(operand))
}
} else if let right = stack.popLast(), let left = stack.popLast() {
switch token {
case "+":
stack.append(left + right)
case "-":
stack.append(left - right)
case "*":
stack.append(left * right)
case "/":
stack.append(left / right)
case "^":
stack.append(pow(left, right))
default:
fatalError("Unexpected operator: \(token)")
}
}
}
return stack.last ?? 0.0
}
}
let calc = EnhancedCalculator()
let expr1 = "3+5*4"
let expr2 = "1+(3+5)*4"
let result1 = calc.calculate(expr1)
print("\(expr1) = \(result1)")
let result2 = calc.calculate(expr2)
print("\(expr2) = \(result2)")