Created
June 20, 2016 14:39
-
-
Save DianQK/d6ef7573ae5e21e04801b2021b5f9d4c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum CalculatorError: ErrorType { | |
case RejectCharacter(Character) // 不接受的字符 | |
case ActionNilXXX // * / 乘除前面没有 可以值 | |
case ActionDuplicate // 符号写一起了,白痴 | |
case ParenthesesDuplicate // 多写了个 ) | |
} | |
enum CalculatorNode: CustomStringConvertible { | |
case number(String) | |
case action(Character) | |
case calculator(Calculator) | |
var description: String { | |
switch self { | |
case .number(let num): | |
return "Number: \(num)" | |
case .action(let char): | |
return "Action: \(char)" | |
case .calculator(let cal): | |
return "Calculator: \(cal.nodes)" | |
} | |
} | |
} | |
extension CalculatorNode: Hashable, Equatable { | |
var hashValue: Int { | |
switch self { | |
case .number(let num): | |
return num.hashValue | |
case .action(let char): | |
return char.hashValue | |
case .calculator(let cal): | |
return "\(cal)".hashValue // == | |
} | |
} | |
} | |
func ==(lhs: CalculatorNode, rhs: CalculatorNode) -> Bool { | |
return lhs.hashValue == rhs.hashValue | |
} | |
class Calculator { | |
private(set) var nodes: [CalculatorNode] = [] | |
private var final = false | |
func add(character character: Character) throws { | |
if ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "."].contains(character) { | |
if let lastNode = nodes.last { | |
switch lastNode { | |
case .number(let num): | |
nodes.removeLast() | |
let newNode = CalculatorNode.number(num + String(character)) | |
nodes.append(newNode) | |
case .action: | |
nodes.append(CalculatorNode.number(String(character))) | |
case .calculator(let cal) where cal.final: | |
nodes.append(CalculatorNode.number(String(character))) | |
case .calculator(let cal) where !cal.final: | |
try cal.add(character: character) | |
default: | |
fatalError("什么鬼,怎么可能走到这里") | |
} | |
} else { | |
nodes.append(CalculatorNode.number(String(character))) | |
} | |
} else if ["+", "-", "*", "/"].contains(character) { | |
if let lastNode = nodes.last { | |
switch lastNode { | |
case .number: | |
nodes.append(CalculatorNode.action(character)) | |
case .action: | |
throw CalculatorError.ActionDuplicate | |
case .calculator(let cal) where cal.final: | |
nodes.append(CalculatorNode.action(character)) | |
case .calculator(let cal) where !cal.final: | |
try cal.add(character: character) | |
default: | |
fatalError("什么鬼,怎么可能走到这里") | |
} | |
} else { | |
nodes.append(CalculatorNode.action(character)) | |
} | |
} else if character == "(" { | |
if let lastNode = nodes.last { | |
switch lastNode { | |
case .number, .action: | |
nodes.append(CalculatorNode.calculator(Calculator())) | |
case .calculator(let cal): | |
try cal.add(character: character) | |
} | |
} else { | |
nodes.append(CalculatorNode.calculator(Calculator())) | |
} | |
} else if character == ")" { | |
if let lastNode = nodes.last { | |
switch lastNode { | |
case .number, .action where final: | |
// throw CalculatorError.ParenthesesDuplicate | |
print("") | |
case .number, .action where !final: | |
final = true | |
case .calculator(let cal) where !cal.final: | |
try cal.add(character: character) | |
case .calculator(let cal) where cal.final: | |
throw CalculatorError.ParenthesesDuplicate | |
default: | |
break | |
} | |
} else { | |
final = true | |
} | |
} else { | |
throw CalculatorError.RejectCharacter(character) | |
} | |
} | |
func currentResult() throws -> Float { | |
var result: Float = 0 | |
// == 先去处理那个括号的优先级 | |
var resultNodes = nodes | |
while true { | |
var finished = true | |
for (index, node) in resultNodes.enumerate() { | |
switch node { | |
case .calculator(let cal): | |
resultNodes.removeAtIndex(index) | |
resultNodes.insert(CalculatorNode.number(String(try cal.currentResult())), atIndex: index) | |
finished = false | |
default: | |
continue | |
} | |
break | |
} | |
if finished { | |
break | |
} | |
} | |
// 处理 */ | |
while true { | |
var finished = true | |
for (index, node) in resultNodes.enumerate() { | |
switch node { | |
case .action(let char) where ["*", "/"].contains(char): | |
if index == 0 { | |
throw CalculatorError.ActionNilXXX | |
} | |
let pre = resultNodes[index - 1] // 没有开头的值是应该挂掉的 | |
let next = resultNodes[index + 1] | |
switch (pre, next) { | |
case (.number(let preNumber), .number(let nextNumber)): | |
let result: Float | |
if char == "*" { | |
result = Float(preNumber)! * Float(nextNumber)! | |
finished = false | |
} else if char == "/" { | |
result = Float(preNumber)! / Float(nextNumber)! | |
finished = false | |
} else { | |
continue | |
} | |
resultNodes.removeAtIndex(index - 1) | |
resultNodes.removeAtIndex(index - 1) | |
resultNodes.removeAtIndex(index - 1) | |
resultNodes.insert(CalculatorNode.number(String(result)), atIndex: index - 1) | |
break | |
default: | |
fatalError() | |
} | |
case .number: | |
continue | |
case .calculator(let cal): | |
resultNodes.removeAtIndex(index) | |
resultNodes.insert(CalculatorNode.number(String(try cal.currentResult())), atIndex: index) | |
default: | |
continue | |
} | |
break | |
} | |
if finished { | |
break | |
} | |
} | |
// +- | |
while resultNodes.count > 1 { | |
for (index, node) in resultNodes.enumerate() { | |
switch node { | |
case .action(let char): | |
let pre = index == 0 ? CalculatorNode.number("0") : resultNodes[index - 1] | |
let next = resultNodes[index + 1] | |
switch (pre, next) { | |
case (.number(let preNumber), .number(let nextNumber)): | |
let result: Float | |
if char == "+" { | |
result = Float(preNumber)! + Float(nextNumber)! | |
} else if char == "-" { | |
result = Float(preNumber)! - Float(nextNumber)! | |
} else { | |
fatalError() | |
} | |
if index == 0 { | |
resultNodes.removeFirst(2) | |
resultNodes.insert(CalculatorNode.number(String(result)), atIndex: index) | |
} else { | |
resultNodes.removeAtIndex(index - 1) | |
resultNodes.removeAtIndex(index - 1) | |
resultNodes.removeAtIndex(index - 1) | |
resultNodes.insert(CalculatorNode.number(String(result)), atIndex: index - 1) | |
} | |
default: | |
fatalError() | |
} | |
case .number: | |
continue | |
case .calculator(let cal): | |
resultNodes.removeAtIndex(index) | |
resultNodes.insert(CalculatorNode.number(String(try cal.currentResult())), atIndex: index) | |
} | |
break | |
} | |
} | |
if let node = resultNodes.first { | |
switch node { | |
case .number(let num): | |
result = Float(num)! | |
case .action, .calculator: | |
fatalError() | |
} | |
} | |
return result | |
} | |
func prase(string: String) throws -> Float { | |
for char in string.characters { | |
try add(character: char) | |
} | |
return try currentResult() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment