Upgrade to Pro — share decks privately, control downloads, hide ads and more …

用 Swift 學習資工系的經典程式問題 1 遞迴(recursive) & 迭代 (iter...

用 Swift 學習資工系的經典程式問題 1 遞迴(recursive) & 迭代 (iterative)

遞迴(recursive)的概念。
多種費波那西(Fibonacci)數列的 recursive 解法和優缺點。
recursive & iterative。
畫畫有趣的謝爾賓斯基三角形 (Sierpinski triangle ) &碎形。
從 Xcode 研究 stack frame。
其它例子: 階乘(factorial)計算,pi 的計算(Leibniz),河內塔(the tower of haoni) 。

More Decks by 愛瘋一切為蘋果的彼得潘

Other Decks in Programming

Transcript

  1. 問題 ? func 最想留留住的幸運() { print("原來來彼得潘是我最想留留住的幸運") print("原來來我們和愛情曾經靠得那麼近") 最想留留住的幸運() } 最想留留住的幸運()

    func 最想留留住的幸運() { print("原來來彼得潘是我最想留留住的幸運") print("原來來我們和愛情曾經靠得那麼近") 最想留留住的幸運() } 最想留留住的幸運() func 最想留留住的幸運() { print("原來來彼得潘是我最想留留住的幸運") print("原來來我們和愛情曾經靠得那麼近") 最想留留住的幸運() } 最想留留住的幸運()
  2. recursive function 需要有結束的 條件 var names = ["彼得潘", "⼩小王⼦子", "虎克",

    "溫蒂"] func 最想留留住的幸運(names: [String], index: Int) { if index < names.count { let name = names[index] if name != "虎克" { print("原來來\(name)是我最想留留住的幸運") print("原來來我們和愛情曾經靠得那麼近") 最想留留住的幸運(names: names, index: index + 1) } } } 最想留留住的幸運(names: names, index: 0)
  3. recursive function 需要有結束的 條件 var names = ["彼得潘", "⼩小王⼦子", "虎克",

    "溫蒂"] func 最想留留住的幸運(names: [String], index: Int) { let space = String(repeating: " ", count: index) print("\(space)開始\(#function) index:\(index)") if index < names.count { let name = names[index] if name != "虎克" { print("\(space)原來來\(name)是我最想留留住的幸運") print("\(space)原來來我們和愛情曾經靠得那麼近") 最想留留住的幸運(names: names, index: index + 1) } } print("\(space)結束\(#function) index:\(index)") } 最想留留住的幸運(names: names, index: 0)
  4. stack frame 從左邊列列表的 frame 順序可看出 function 呼叫的順序 frame 順序是由新到舊, frame

    0是最新最後⼀一個執⾏行行的 function frame 1 的 function 裡呼叫了了 frame 0 的 function 可從 stack frame 查 App 閃退最後執⾏行行的程式
  5. App 裡執⾏行行永不結束的 recursive function func 最想留留住的幸運() { print("原來來彼得潘是我最想留留住的幸運") print("原來來我們和愛情曾經靠得那麼近") 最想留留住的幸運()

    } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. 最想留留住的幸運() }
  6. Fibonacci sequence 費波那⻄西數列列 0, 1, 1, 2, 3, 5, 8,

    13, 21... 規則是 ? https://www.mathsisfun.com/numbers/fibonacci-sequence.html
  7. Fibonacci sequence 費波那⻄西數列列 0, 1, 1, 2, 3, 5, 8,

    13, 21... 數字是前兩兩個數字加起來來 ( 從第三個數字開始)
  8. Fibonacci sequence 第⼀一版 func fibonacciSequence(index: Int) -> Int { return

    fibonacciSequence(index: index - 1) + fibonacciSequence(index: index - 2) } fibonacciSequence(index: 3)
  9. Fibonacci sequence 第⼆二版 func fibonacciSequence(index: Int) -> Int { if

    index < 2 { return index } else { return fibonacciSequence(index: index - 1) + fibonacciSequence(index: index - 2) } } fibonacciSequence(index: 3)
  10. Fibonacci sequence 第三版 var fiboDic = [0: 0, 1: 1]

    func fibonacciSequence(index: Int) -> Int { if let number = fiboDic[index] { return number } else { fiboDic[index] = fibonacciSequence(index: index - 1) + fibonacciSequence(index: index - 2) return fiboDic[index]! } } fibonacciSequence(index: 10)
  11. fibonacciSequence 呼叫了了 10 + 9 次 10 + 9 <

    89 + 88 有更更快的⽅方法嗎 ?
  12. Fibonacci sequence 第四版 iterative: 利利⽤用迴圈 func fibonacciSequence(index: Int) -> Int

    { if index < 2 { return index } else { var firstNumber = 0 var secondNumber = 1 for _ in 2...index { let newNumber = firstNumber + secondNumber firstNumber = secondNumber secondNumber = newNumber } return secondNumber } } fibonacciSequence(index: 10)
  13. 利利⽤用 tuple func fibonacciSequence(index: Int) -> Int { if index

    < 2 { return index } else { var firstNumber = 0 var secondNumber = 1 for _ in 2...index { (firstNumber, secondNumber) = (secondNumber, firstNumber + secondNumber) } return secondNumber } } https://bit.ly/2zNt2uO
  14. Iteration & Recursion • Recursion 的好: • 程式可能比較精簡 • 想到規則後,可能比較好寫

    • Recursion 的壞: • 比較難懂 • 可能比較慢 • 可能⽤用比較多記憶體
  15. 九九乘法 Iteration for i in 1...9 { for j in

    1...9 { print("\(i) * \(j) = \(i * j)") } }
  16. 九九乘法 Recursion func timesTable(number1: Int, number2: Int) { print("\(number1) *

    \(number2) = \(number1 * number2)") if number2 < 9 { timesTable(number1: number1, number2: number2 + 1) } else if number1 < 9 { timesTable(number1: number1 + 1, number2: 1) } } timesTable(number1: 1, number2: 1) 規則: 兩兩個數字相乘
  17. 河內塔 the tower of haoni ⼩小的盤⼦子要放在⼤大的盤⼦子上 ⽬目標: 將 A 的盤⼦子搬到

    C 上 http://www.chiuchang.com.tw/toy/hanoi/hanoi.html Recursive 難在找規則 剛剛的 Fibonacci sequence 規則很明顯
  18. ⼀一個盤⼦子 ? A B C A B C 1 2

    有 A, B, C 三個塔,將 A 的盤⼦子搬到 C
  19. 兩兩個盤⼦子 ? A B C A B C 1 2

    將 A 上比較⼩小的盤⼦子移到 B,才能將⼤大的盤⼦子到移到 C
  20. 兩兩個盤⼦子 ? A B C A B C 3 4

    剩⼀一個盤⼦子,直接搬
  21. 三個盤⼦子 ? A B C A B C 將 A

    上比較⼩小的兩兩個盤⼦子移到 B,才能將最⼤大的盤⼦子到移到 C (可以先想像 A 上最⼤大的盤⼦子不存在, 參參考兩兩個盤⼦子的步驟將 A 的兩兩個盤⼦子移到 B) 1 2 B ⼜又要當⼯工具⼈人了了 !
  22. 三個盤⼦子 ? A B C A B C 已完成將 A

    之上的兩兩個盤⼦子移到 B (參參考兩兩個盤⼦子的步驟) 3 4
  23. 三個盤⼦子 ? A B C A B C 接下來來將 B

    之上的兩兩個盤⼦子移到 C (可以當成 C 上的盤⼦子不存在,參參考兩兩個盤⼦子的步驟) 4 5
  24. 四個盤⼦子 ? A B C 將 A 上比較⼩小的三個盤⼦子移到 B,才能將最⼤大的盤⼦子到移到 C

    (可以先想像 A 上最⼤大的盤⼦子不存在, 參參考三個盤⼦子的步驟將 A 的三個盤⼦子移到 B)
  25. 規則 有 A, B, C 三個塔,將 A 的盤⼦子搬到 C •

    1 個盤⼦子 • 直接搬 • 2 個盤⼦子 • 將 A 上比較⼩小的 1(2-1)個盤⼦子移到 B,然後再將最⼤大的盤⼦子到移到 C。接下來來再 將 B 上的 1 盤⼦子移到 C。 • 3 個盤⼦子 • 將 A 上比較⼩小的 2(3-1)個盤⼦子移到 B,然後再將最⼤大的盤⼦子到移到 C。接下來來再 將 B 上的 2 盤⼦子移到 C。 • 4 個盤⼦子 • 將 A 上比較⼩小的 3(4-1)個盤⼦子移到 B,然後再將最⼤大的盤⼦子到移到 C。接下來來再 將 B 上的 3 盤⼦子移到 C。
  26. 規則 • 當 tower上有 n ( > 1) 個盤⼦子時 •

    將 tower 上比較⼩小的 (n-1) 個盤⼦子移到輔助的 tower。 (⼯工具⼈人) • 將 tower 上最⼤大的盤⼦子到移到⽬目標的 tower • 將輔助的 tower 的盤⼦子移到⽬目標的 tower。 • 當剩下⼀一個盤⼦子時,可以直接移到⽬目標的 tower。
  27. 畫個同⼼心圓吧 import UIKit class ConcentricCirclesView: UIView { func drawCircle(in rect:

    CGRect) { if rect.width > 20 { let path = UIBezierPath(roundedRect: rect, cornerRadius: rect.width / 2) UIColor.orange.setStroke() path.stroke() let width = rect.width / 2 let x = self.bounds.midX - width / 2 drawCircle(in: CGRect(x: x, y: x, width: width, height: width)) } } override func draw(_ rect: CGRect) { drawCircle(in: rect) } } let concentricCirclesView = ConcentricCirclesView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
  28. 如何練習 recursion 練習,練習,練習 • 階層( factorial) • ex: 3! =

    1 * 2 * 3 = 6 • Digits: 從數字產⽣生包含每⼀一位數字的 array • ex: 1234 -> [1, 2, 3, 4] • Power:計算次⽅方 • ex: 5 3 • Euclidian algorithm: 兩兩個整數的最⼤大公因數 • 9 & 6 > 3 • Binary Search • ex: binarySearch(2, [1, 2, 4, 5 ,7, 9]) > true https://www.weheartswift.com/recursion/