Код написал для выборки числа из входного массива
//: Playground - noun: a place where people can play
extension String {
func toDouble() -> Double? {
// numberFromString это метод класса NSNumberFormatter, он извлекает из строки число
// возвращает либо число либо nil
// Этот метод имеет свойство doubleValue
return NSNumberFormatter().numberFromString(self)?.doubleValue
}
}
import Cocoa
var opStack = [Double]()
var str = "123,4Hello, play345,65ground"
var parse = Array(str)
func numberIs(symbol:String){
// Делаем клон входного массива
var temp = parse.map(){String($0)}
// Добавляем к нему слева анализируемый символ
temp.insert(symbol, atIndex: 0)
// Удаляем все элементы из массива которые не образуют число, справа-налево
while true {
let total = temp.reduce("") {
return $0 + $1
}
if let oo = total.toDouble(){
break
}else{
temp.removeLast()
}
}
// Вычисляем число
let number = temp.reduce("") {
return $0 + $1
}
// Помещаем его в выходной стек
opStack += [number.toDouble()!]
// Удаляем из входного массива все элементы числа переданного в выходной массив
let count = temp.count - 1
for var i=0; i < count; ++i {
parse.removeAtIndex(0)
}
}
numberIs("4")
parse
8. Если токен является оператором *, /, + или -, поместить его в opstack. Однако, перед этим вытолкнуть любой из операторов, уже находящихся в opstack, если он имеет больший или равный приоритет, и добавить его в результирующий список.
// Создаем отображение массива stack
var ref = stack.map{$0.precedence}
//Удаляем все элементы которые больше s слева направо до тех пор пока s <= clone.first
while !ref.isEmpty {
if s <= ref.first {
ref.removeAtIndex(0)
}else{
break
}
}
// Считаем разницу между длинами массивов
let n = stack.count - ref.count
// Удаляем из stack количество элементов n
// и вставляем их в opStack
for var i=0;i<n;++i{
let oo = stack.removeAtIndex(0)
if let operation = knownOps[oo.description]{
opStack += [operation]
}else{}
}
}
var scale: CGFloat = 2.0 { didSet { setNeedsDisplay() } }
var origin: CGPoint = CGPoint(x: 190, y: 340) { didSet { setNeedsDisplay() } }
AxesDrawer(contentScaleFactor: contentScaleFactor)
.drawAxesInRect(bounds, origin: origin, pointsPerUnit: sale)
http://cs193p.m2m.at/cs193p-project-3-assignment-3-task-7-winter-2015/
Относительно манипуляций над графиком и осями координат
Вот так рисую график
import UIKit
class Draw2D2: UIView {
var graph = CalculatorGraphic()
override func drawRect(rect: CGRect) {
// 1. Размеры и положение rect не меняем
// 2. Меняем положение origin для системы координат от плюс бесконечности до минус бесконечности по ширине
// и от плюс до минус бесконечности по высоте
// 3. Меняем масштаб для графика и для системы координат одновременно
let origin: CGPoint = CGPointMake(self.center.x - 30 , self.center.y - 10 )
// Вычисляем функцию по точкам на оси Х внутри rect и рисуем график
let scale: CGFloat = 1.2
let str = "200*cos(M*0.03)"
// Рисуем график
drawGraphicFunction(rect,origin: origin,scale: scale, str: str)
// Рисуем оси координат внутри rect
drawAxes(rect, origin: origin, scale: scale)
// Рисуем текст
drawText(str)
}
func drawGraphicFunction(rect: CGRect,origin : CGPoint, scale : CGFloat, str: String){
// Строим стек для расчета функции
graph.parseString(str)
// Для создания графика функции надо определить диапазоны отрицательных и положительных значений
// Известны положения двух точек
// original - точка отсчета рисуемых на view осей системы координат
// rect.original - точка отсчета системы координат прямоугольника области построения графика
let context = UIGraphicsGetCurrentContext()
CGContextSetLineWidth(context, 2.0)
CGContextSetStrokeColorWithColor(context,
UIColor.blueColor().CGColor)
// расстояние по оси х от левой границы rect до точки начала координат рисуемых осей
// В нашем случае rect.origin.x всегда равно нулю
// Положение точки origin задается относительно rect.origin
// Поэтому если origin находится левее rect.origin left будет положительным
// и наоборот если origin находится правее rect.origin то left будет отрицательным
let left:Int = Int((rect.minX - origin.x)/scale)
// расстояние по оси х от точки начала координат рисуемых осей до правой границы прямоугольника построения
//let right:Int = Int((rect.origin.x + rect.width - origin.x)/scale)
let right:Int = Int((rect.maxX - origin.x)/scale)
// Рассчитываем функцию
var data = graph.graphData(left,right: right)
// Рисуем функцию
while !data.isEmpty {
let point = data.removeAtIndex(0)
println(point.x)
println(point.y)
if (point.x == CGFloat(left)) {
//----------------------------------------------
CGContextMoveToPoint(context, point.x*scale+origin.x, -point.y*scale+origin.y)
}
else {
CGContextAddLineToPoint(context, point.x*scale+origin.x, -point.y*scale+origin.y)
}
}
CGContextStrokePath(context)
}
func drawAxes(rect : CGRect, origin : CGPoint, scale: CGFloat){
let bounds = rect
AxesDrawer(contentScaleFactor: contentScaleFactor)
.drawAxesInRect(bounds, origin: origin, pointsPerUnit: scale)
}
func drawText(str: String){
let numberOne = str
let numberOneRect = CGRectMake(self.bounds.maxX - 360, self.bounds.maxY - 80, 350, 50)
let font = UIFont(name: "Academy Engraved LET", size: 24)
let textStyle = NSMutableParagraphStyle.defaultParagraphStyle()
let numberOneAttributes = [
NSFontAttributeName: font!]
numberOne.drawInRect(numberOneRect,
withAttributes:numberOneAttributes)
}
}
Можно посмотреть как калькулятор работает с splitViewController
Класс AxesDrawer
// Если начало координат не находится внутри фрейма
// ???
if !CGRectContainsPoint(bounds, origin) {
let leftx = max(origin.x - bounds.maxX, 0)
println("leftx = \(max(origin.x - bounds.maxX, 0))")
let rightx = max(bounds.minX - origin.x, 0)
println("rightx = \(max(bounds.minX - origin.x, 0))")
let downy = max(origin.y - bounds.minY, 0)
println("downy = \(max(origin.y - bounds.minY, 0))")
let upy = max(bounds.maxY - origin.y, 0)
println("upy = \(max(bounds.maxY - origin.y, 0))")
// Определили startingHashmarkRadius как минимум из минимумов min(min(leftx, rightx), min(downy, upy))
startingHashmarkRadius = min(min(leftx, rightx), min(downy, upy)) / pointsPerHashmark + 1
println("min(leftx, rightx) = \(min(leftx, rightx))")
println("min(downy, upy) = \(min(downy, upy))")
println("min = \(min(min(leftx, rightx), min(downy, upy)) / pointsPerHashmark)")
//println("startingHashmarkRadius = \(startingHashmarkRadius)")
}