I'm trying to do the assignments that are issued in the lectures but of course... I'm stuck on the first assignment and I hate moving forward without being able to solve something.
I'm having issues implementing π as both an operation and and operand. I have it working as an operation(all it does is return the value of π). E.g. ' π Enter π Enter + ' results in 6.28... but if I say ' π Enter π Enter + π Enter ÷ ' it results in 1.0 when it should be 2.0
I've searched StackOverflow and found nothing aside from Objective-C solutions. Any help is appreciated.
Here is the action fired in the ViewController when you tap an operation:
@IBAction func operate(sender: UIButton) {
let operand = sender.currentTitle!
if (userIsInTheMiddleOfTypingANumber){
enter()
}
if let operation = sender.currentTitle{
if let result = brain.performOperation(operation){
displayValue = result
} else {
displayValue = 0
}
}
}
Here is the code from the model:
private enum Op: Printable {
case Operand(Double)
case UnaryOperator(String, Double -> Double)
case BinaryOperator(String, (Double, Double) -> Double)
case ConstantOperator (String, Double)
var description: String {
get {
switch self {
case .Operand(let operand):
return "\(operand)"
case .UnaryOperator(let symbol, _ ):
return symbol
case .BinaryOperator(let symbol, _ ):
return symbol
case .ConstantOperator(let symbol, _ ):
return symbol
}
}
}
}
func performOperation(symbol: String) -> Double? {
if let operation = knownOps[symbol]{
opStack.append(operation)
}
return evaluate()
}
private var opStack = [Op]()
private var knownOps = [String:Op]()
init(){
func learnOp(op: Op){
knownOps[op.description] = op
}
learnOp(Op.BinaryOperator("✕", *))
//knownOps["✕"] = Op.BinaryOperator("✕", *)
knownOps["÷"] = Op.BinaryOperator("÷") {$1 / $0}
knownOps["+"] = Op.BinaryOperator("+", +)
knownOps["−"] = Op.BinaryOperator("−") {$1 - $0}
knownOps["√"] = Op.UnaryOperator("√", sqrt)
learnOp(Op.UnaryOperator("cos", cos))
learnOp(Op.UnaryOperator("sin", sin))
learnOp(Op.ConstantOperator("∏", M_PI))
}
private func evaluate(ops: [Op]) -> (result: Double?, remainingOps: [Op]){
if !ops.isEmpty {
var remainingOps = ops
let op = remainingOps.removeLast() //get the first op off the stack
switch op {
case .Operand(let operand):
return (operand, remainingOps)
case .UnaryOperator(_, let operation):
let operationEvaluation = evaluate(remainingOps)
if let operand = operationEvaluation.result {
return(operation(operand), operationEvaluation.remainingOps)
}
case .BinaryOperator(_ , let operation):
let op1Eval = evaluate(remainingOps)
if let op1 = op1Eval.result{
let op2Eval = evaluate(op1Eval.remainingOps)
if let op2 = op2Eval.result {
return (operation(op1, op2), op2Eval.remainingOps)
}
}
case .ConstantOperator(_, let value):
return(value, remainingOps)
}
}
return(nil, ops)
}
func evaluate() -> Double? {
let (result, remainder) = evaluate(opStack)
println("\(opStack) = \(result) with \(remainder) left over.")
return result
}
Note: I'm trying to complete the assignment's required tasks given the structure the instructor wants us to follow. My attempt here (trying to add ∏ as an operator) works in certain situations but not all...
Here is what the assignment says about this task: "The value of π is available via the expression M_PI. E.g. let x = M_PI. You can think of π as an operand or you can think of it as an operation (i.e. a new kind of operation that takes no arguments off the stack but returns a value). Up to you. But, either way, it’d be nice to be able to add other constants to your Calculator with a minimum of code."
I tried the operand approach but I was breaking the MVC paradigms so I stopped.
If you press π and enter then you are effectively putting pi in the opStack twice. So you are actually doing π π π π + π π ÷. Does that make sense? In order to add pi to itself, you'd push π π +. If you wanted to add pi together and then divide by pi, it would be π π + π ÷.