import Foundation
class Calculator {
private let precedence: [Character: Int] = ["+": 1, "-": 1, "*": 2, "/": 2, "^": 3, "√": 3]
private let associativity: [Character: Character] = ["+": 'L', "-": 'L', "*": 'L', "/": 'L', "^": 'R', "√": 'R']
func infixToPostfix(expression: String) -> [String] {
var output: [String] = []
var operators: [Character] = []
var tokens = expression.split(whereSeparator: { $0 == " " }).map(String.init)
for token in tokens {
if let _ = Double(token) {
output.append(token)
} else if let firstChar = token.first, firstChar == "(" {
operators.append(firstChar)
} else if let firstChar = token.first, firstChar == ")" {
while let op = operators.last, op != "(" {
output.append(String(operators.removeLast()))
}
if let op = operators.last, op == "(" {
operators.removeLast()
}
} else if let op = token.first, precedence.keys.contains(op) {
while let lastOp = operators.last, lastOp != "(" && (precedence[lastOp]! > precedence[op]! || (precedence[lastOp]! == precedence[op]! && associativity[op]! == 'L')) {
output.append(String(operators.removeLast()))
}
operators.append(op)
}
}
while let op = operators.last {
output.append(String(operators.removeLast()))
}
return output
}
func evaluatePostfix(postfix: [String]) -> Double {
var stack: [Double] = []
for token in postfix {
if let num = Double(token) {
stack.append(num)
} else if token.count == 1, let op = token.first {
switch op {
case "+":
let b = stack.removeLast()
let a = stack.removeLast()
stack.append(a + b)
case "-":
let b = stack.removeLast()
let a = stack.removeLast()
stack.append(a - b)
case "*":
let b = stack.removeLast()
let a = stack.removeLast()
stack.append(a * b)
case "/":
let b = stack.removeLast()
let a = stack.removeLast()
stack.append(a / b)
case "^":
let b = stack.removeLast()
let a = stack.removeLast()
stack.append(pow(a, b))
case "√":
let a = stack.removeLast()
stack.append(sqrt(a))
default:
break
}
}
}
return stack.removeLast()
}
}
let calc = Calculator()
let expression = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"
let postfix = calc.infixToPostfix(expression: expression)
let result = calc.evaluatePostfix(postfix: postfix)
print("Postfix Expression: \(postfix.joined(separator: " "))")
print("Result: \(result)")