Skip to content

Instantly share code, notes, and snippets.

@focuspirit
Last active August 29, 2015 14:14
Show Gist options
  • Save focuspirit/89fc83621ee8c4e3e511 to your computer and use it in GitHub Desktop.
Save focuspirit/89fc83621ee8c4e3e511 to your computer and use it in GitHub Desktop.
import Foundation
class CalculatorBrain
{
private enum Op: Printable
{
case Operand(Double)
case UnaryOperation(String, Double -> Double)
case BinaryOperation(String, (Double, Double) -> Double)
var description: String {
get {
switch self {
case .Operand(let operand):
return "\(operand)"
case .UnaryOperation(let symbol, _):
return symbol
case .BinaryOperation(let symbol, _):
return symbol
}
}
}
}
private var opStack = [Op]()
private var knownOps = [String:Op]()
init() {
func learnOp(op: Op) {
knownOps[op.description] = op
}
knownOps["×"] = Op.BinaryOperation("×", *)
knownOps["÷"] = Op.BinaryOperation("÷") { $1 / $0}
knownOps["+"] = Op.BinaryOperation("+", +)
knownOps["−"] = Op.BinaryOperation("−") { $1 - $0}
knownOps["√"] = Op.UnaryOperation("√", sqrt)
}
private func evaluate(ops: [Op]) -> (result: Double?, remainingOps: [Op])
{
if !ops.isEmpty {
var remainingOps = ops
let op = remainingOps.removeLast()
switch op {
case .Operand(let operand):
return (operand, remainingOps)
case .UnaryOperation(_, let operation):
let operandEvaluation = evaluate(remainingOps)
if let operand = operandEvaluation.result {
return (operation(operand), operandEvaluation.remainingOps)
}
case .BinaryOperation(_, let operation):
let op1Evaluation = evaluate(remainingOps)
if let operand1 = op1Evaluation.result {
let op2Evaluation = evaluate(op1Evaluation.remainingOps)
if let operand2 = op2Evaluation.result {
return (operation(operand1, operand2), op2Evaluation.remainingOps)
}
}
}
}
return (nil, ops)
}
func evaluate() -> Double? {
let (result, remainder) = evaluate(opStack)
println("\(opStack) = \(result) with \(remainder) left over")
return result
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment