-
Notifications
You must be signed in to change notification settings - Fork 0
/
CalculatorBrain.swift
77 lines (66 loc) · 2.26 KB
/
CalculatorBrain.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//
// CalculatorBrain.swift
// Calculator
//
// Created by Miwand Najafe on 2015-07-13.
// Copyright (c) 2015 Miwand Najafe. All rights reserved.
//
import Foundation
class CalculatorBrain
{
private enum Op {
case Operand(Double)
case UnaryOperation(String, Double -> Double)
case BinaryOperation (String, (Double, Double) -> Double)
}
private var opStack = [Op]()
func pushOperand(operand: Double) -> Double? {
opStack.append(Op.Operand(operand))
return evaluate()
}
private var knownOps = [String:Op]()
init(){
knownOps["✕"] = Op.BinaryOperation("✕"){ $0 * $1 }
knownOps["+"] = Op.BinaryOperation("+"){ $0 + $1 }
knownOps["÷"] = Op.BinaryOperation("÷"){ $1 / $0 }
knownOps["-"] = Op.BinaryOperation("-"){ $1 - $0 }
knownOps["√"] = Op.UnaryOperation("√"){ sqrt($0) }
}
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)
return result
}
func performOperation(symbol: String) {
if let operation = knownOps [symbol] {
opStack.append(operation)
}
}
}