KEMBAR78
Swift에서 꼬리재귀 사용기 (Tail Recursion) | PDF
{
func fac(_ n: Int) -> Int {
guard n > 0 else { return 1 }
return n * fac(n-1)
}
fac(4)
➔ 4 * fac(3)
➔ 4 * 3 * fac(2)
➔ 4 * 3 * 2 * fac(1)
➔ 4 * 3 * 2 * 1 * fac(0)
➔ 4 * 3 * 2 * 1 * 1
➔ 4 * 3 * 2 * 1
➔ 4 * 3 * 2
➔ 4 * 6
➔ 24
func fac(_ n: Int) -> Int {
func fac(_ index: Int, _ answer: Int) -> Int {
if index == 1 {
return answer
}
return fac(index-1, answer * index)
}
return fac(n,1)
}
fac(4)
➔ fac(4,1)
➔ fac(3,4)
➔ fac(2,12)
➔ fac(1,24)
➔ 24
.
{
func fib(_ n: Int) -> Int {
if n == 0 { return 0 }
if n == 1 { return 1 }
return fib(n-1) + fib(n-2)
}
fib(5)
fib(4) fib(3)
fib(1)
1
fib(2)
fib(0)
0
fib(1)
1
fib(2)
fib(0)
0
fib(1)
1
fib(3)
fib(1)
1
fib(2)
fib(0)
0
fib(1)
1
func fib(_ n: Int) -> Int {
func fib(_ a: Int, _ b: Int, _ n: Int) -> Int {
if n == 0 { return a }
return fib(b, a+b, n-1)
}
return fib(0,1,n)
}
fib(6)
➔ fib(0,1,6)
➔ fib(1,1,5)
➔ fib(1,2,4)
➔ fib(2,3,3)
➔ fib(3,5,2)
➔ fib(5,8,1)
➔ fib(8,13,0)
➔ 8
fac(4)
➔ fac(4,1)
➔ fac(3,4)
➔ fac(2,12)
➔ fac(1,24)
➔ 24
fac(4)
➔ 4 * fac(3)
➔ 4 * 3 * fac(2)
➔ 4 * 3 * 2 * fac(1)
➔ 4 * 3 * 2 * 1 * fac(0)
➔ 4 * 3 * 2 * 1 * 1
➔ 4 * 3 * 2 * 1
➔ 4 * 3 * 2
➔ 4 * 6
➔ 24
: https://brunch.co.kr/@sunghokimnxag/5
8
• 1 .
• index 7 (7,14,21…) 7 (7,17,27) .
• 1, 2, 3, 4, 5, 6, [7], 6, 5, 4, 3, 2, 1, [0], 1, 2, [3], 2, 1, 0, [-1], 0, 1,…
• pingpong(x) .
• For Loop Array .
• Assignment , .
• String .
pingpong(8) = 6
pingpong(22) = 0
pingpong(68) = 2
pingpong(100) = 2
func has7(_ index: Int) -> Bool {
if index % 7 == 0 {
return true
}
if (index - 7) % 10 == 0 {
return true
}
if (index / 10) > 1 {
return has7(index/10)
}
return false
}
has7(21)
➔ true
has7(723)
➔ has7(72)
➔ has7(7)
➔ true
has7(123)
➔ has7(12)
➔ has7(1)
➔ false
unc pingpong(_ index: Int) -> Int {
func pingpong(_ index: Int) -> (Int, Int) {
if index == 1 {
return (1, 1)
}
switch pingpong( index - 1 ) {
case let (answer, direction) :
if has7(index) {
return (answer+direction, -direction)
} else {
return (answer+direction, direction)
}
}
}
return pingpong(index).0
pingpong(14) ➔ (pingpong(13).answer-1, 1)
pingpong(13) ➔ (pingpong(12).answer-1, -1)
pingpong(12) ➔ (pingpong(11).answer-1, -1)
pingpong(11) ➔ (pingpong(10).answer-1, -1)
pingpong(10) ➔ (pingpong( 9).answer-1, -1)
pingpong(9) ➔ (pingpong( 8).answer-1, -1)
pingpong(8) ➔ (pingpong( 7).answer-1, -1)
pingpong(7) ➔ (pingpong( 6).answer+1, -1)
pingpong(6) ➔ (pingpong( 5).answer+1, 1)
pingpong(5) ➔ (pingpong( 4).answer+1, 1)
pingpong(4) ➔ (pingpong( 3).answer+1, 1)
pingpong(3) ➔ (pingpong( 2).answer+1, 1)
pingpong(2) ➔ (pingpong( 1).answer+1, 1)
pingpong(1) ➔ (1,1)
nc pingpong(_ count: Int) -> Int {
func pp(_ count: Int, _ index: Int, _ direction: Int, _ answer: Int) -> Int {
if count == index {
return answer
}
if has7(index+1) {
return pp(count, index+1, -direction, answer+direction)
} else {
return pp(count, index+1, direction, answer+direction)
}
}
return pp(count, 1, 1, 1)
pp(14, index: 1, direction: 1,answer: 1)
pp(14, index: 2, direction: 1,answer: 2)
pp(14, index: 3, direction: 1,answer: 3)
pp(14, index: 4, direction: 1,answer: 4)
pp(14, index: 5, direction: 1,answer: 5)
pp(14, index: 6, direction:-1,answer: 6)
pp(14, index: 7, direction:-1,answer: 7)
pp(14, index: 8, direction:-1,answer: 6)
pp(14, index: 9, direction:-1,answer: 5)
pp(14, index:10, direction:-1,answer: 4)
pp(14, index:11, direction:-1,answer: 3)
pp(14, index:12, direction:-1,answer: 2)
pp(14, index:13, direction: 1,answer: 1)
➔ 0
let array = [1,3,5,23,15]
func sum(array: [Int], initial: Int) -> Int {
guard let head = array.first else { return initial }
let tail = Array(array.dropFirst())
return sum(array: tail, initial: initial + head)
}
sum(array: array, initial: 0)
➔ sum(array: [1,3,5,23,15], initial: 0)
➔ sum(array: [3,5,23,15], initial: 1)
➔ sum(array: [5,23,15], initial: 4)
➔ sum(array: [23,15], initial: 9)
➔ sum(array: [15], initial: 32)
➔ sum(array: [], initial: 47)
➔ 47
func tailRecursive(array: [Int] ,
initial: Int,
eachOperation: (Int, Int) -> Int ) -> Int {
guard let head = array.first else { return initial }
let tail = Array(array.dropFirst())
return tailRecursive(array: tail,
initial: eachOperation(head, initial),
eachOperation: eachOperation)
}
tailRecursive(array: array,
initial: 0,
eachOperation:{(element: Int, answer: Int)->Int in
element + answer
})
➔ 47
extension Array {
func tailRecursive<Result>(
_ initial: Result,
eachOperation: (Result, Element) -> Result ) -> Result {
guard let head = self.first else { return initial }
let tail = Array(self.dropFirst())
return tail.tailRecursive(eachOperation(initial, head),
eachOperation: eachOperation)
}
}
array.tailRecursive(0, eachOperation: + )
array.tailRecursive(0) { (element: Int, answer: Int) -> Int in
return element + answer
}
array.reduce(0) { (element: Int, answer) -> Int in
return element + answer
}
Array(1...5).reduce(1, *)
• .
• .
-> .
-> ex)
-> .
func searchTopViewController(viewController: UIViewController?) -> UIViewController? {
guard let viewController = viewController else { return nil }
switch viewController {
case let viewController as UITabBarController:
return searchTopViewController(viewController: viewController.selectedViewController)
case let viewController as UINavigationController:
return searchTopViewController(viewController: viewController.viewControllers.last)
case let viewController where viewController.presentedViewController != nil:
return searchTopViewController(viewController:viewController.presentedViewController)
default:
return viewController
}
}
•
•
•
• Reduce
•

Swift에서 꼬리재귀 사용기 (Tail Recursion)

  • 3.
  • 4.
    func fac(_ n:Int) -> Int { guard n > 0 else { return 1 } return n * fac(n-1) } fac(4) ➔ 4 * fac(3) ➔ 4 * 3 * fac(2) ➔ 4 * 3 * 2 * fac(1) ➔ 4 * 3 * 2 * 1 * fac(0) ➔ 4 * 3 * 2 * 1 * 1 ➔ 4 * 3 * 2 * 1 ➔ 4 * 3 * 2 ➔ 4 * 6 ➔ 24
  • 5.
    func fac(_ n:Int) -> Int { func fac(_ index: Int, _ answer: Int) -> Int { if index == 1 { return answer } return fac(index-1, answer * index) } return fac(n,1) } fac(4) ➔ fac(4,1) ➔ fac(3,4) ➔ fac(2,12) ➔ fac(1,24) ➔ 24 .
  • 6.
  • 7.
    func fib(_ n:Int) -> Int { if n == 0 { return 0 } if n == 1 { return 1 } return fib(n-1) + fib(n-2) } fib(5) fib(4) fib(3) fib(1) 1 fib(2) fib(0) 0 fib(1) 1 fib(2) fib(0) 0 fib(1) 1 fib(3) fib(1) 1 fib(2) fib(0) 0 fib(1) 1
  • 8.
    func fib(_ n:Int) -> Int { func fib(_ a: Int, _ b: Int, _ n: Int) -> Int { if n == 0 { return a } return fib(b, a+b, n-1) } return fib(0,1,n) } fib(6) ➔ fib(0,1,6) ➔ fib(1,1,5) ➔ fib(1,2,4) ➔ fib(2,3,3) ➔ fib(3,5,2) ➔ fib(5,8,1) ➔ fib(8,13,0) ➔ 8
  • 9.
    fac(4) ➔ fac(4,1) ➔ fac(3,4) ➔fac(2,12) ➔ fac(1,24) ➔ 24 fac(4) ➔ 4 * fac(3) ➔ 4 * 3 * fac(2) ➔ 4 * 3 * 2 * fac(1) ➔ 4 * 3 * 2 * 1 * fac(0) ➔ 4 * 3 * 2 * 1 * 1 ➔ 4 * 3 * 2 * 1 ➔ 4 * 3 * 2 ➔ 4 * 6 ➔ 24
  • 11.
    : https://brunch.co.kr/@sunghokimnxag/5 8 • 1. • index 7 (7,14,21…) 7 (7,17,27) . • 1, 2, 3, 4, 5, 6, [7], 6, 5, 4, 3, 2, 1, [0], 1, 2, [3], 2, 1, 0, [-1], 0, 1,… • pingpong(x) . • For Loop Array . • Assignment , . • String . pingpong(8) = 6 pingpong(22) = 0 pingpong(68) = 2 pingpong(100) = 2
  • 12.
    func has7(_ index:Int) -> Bool { if index % 7 == 0 { return true } if (index - 7) % 10 == 0 { return true } if (index / 10) > 1 { return has7(index/10) } return false } has7(21) ➔ true has7(723) ➔ has7(72) ➔ has7(7) ➔ true has7(123) ➔ has7(12) ➔ has7(1) ➔ false
  • 13.
    unc pingpong(_ index:Int) -> Int { func pingpong(_ index: Int) -> (Int, Int) { if index == 1 { return (1, 1) } switch pingpong( index - 1 ) { case let (answer, direction) : if has7(index) { return (answer+direction, -direction) } else { return (answer+direction, direction) } } } return pingpong(index).0 pingpong(14) ➔ (pingpong(13).answer-1, 1) pingpong(13) ➔ (pingpong(12).answer-1, -1) pingpong(12) ➔ (pingpong(11).answer-1, -1) pingpong(11) ➔ (pingpong(10).answer-1, -1) pingpong(10) ➔ (pingpong( 9).answer-1, -1) pingpong(9) ➔ (pingpong( 8).answer-1, -1) pingpong(8) ➔ (pingpong( 7).answer-1, -1) pingpong(7) ➔ (pingpong( 6).answer+1, -1) pingpong(6) ➔ (pingpong( 5).answer+1, 1) pingpong(5) ➔ (pingpong( 4).answer+1, 1) pingpong(4) ➔ (pingpong( 3).answer+1, 1) pingpong(3) ➔ (pingpong( 2).answer+1, 1) pingpong(2) ➔ (pingpong( 1).answer+1, 1) pingpong(1) ➔ (1,1)
  • 14.
    nc pingpong(_ count:Int) -> Int { func pp(_ count: Int, _ index: Int, _ direction: Int, _ answer: Int) -> Int { if count == index { return answer } if has7(index+1) { return pp(count, index+1, -direction, answer+direction) } else { return pp(count, index+1, direction, answer+direction) } } return pp(count, 1, 1, 1) pp(14, index: 1, direction: 1,answer: 1) pp(14, index: 2, direction: 1,answer: 2) pp(14, index: 3, direction: 1,answer: 3) pp(14, index: 4, direction: 1,answer: 4) pp(14, index: 5, direction: 1,answer: 5) pp(14, index: 6, direction:-1,answer: 6) pp(14, index: 7, direction:-1,answer: 7) pp(14, index: 8, direction:-1,answer: 6) pp(14, index: 9, direction:-1,answer: 5) pp(14, index:10, direction:-1,answer: 4) pp(14, index:11, direction:-1,answer: 3) pp(14, index:12, direction:-1,answer: 2) pp(14, index:13, direction: 1,answer: 1) ➔ 0
  • 15.
    let array =[1,3,5,23,15] func sum(array: [Int], initial: Int) -> Int { guard let head = array.first else { return initial } let tail = Array(array.dropFirst()) return sum(array: tail, initial: initial + head) } sum(array: array, initial: 0) ➔ sum(array: [1,3,5,23,15], initial: 0) ➔ sum(array: [3,5,23,15], initial: 1) ➔ sum(array: [5,23,15], initial: 4) ➔ sum(array: [23,15], initial: 9) ➔ sum(array: [15], initial: 32) ➔ sum(array: [], initial: 47) ➔ 47
  • 16.
    func tailRecursive(array: [Int], initial: Int, eachOperation: (Int, Int) -> Int ) -> Int { guard let head = array.first else { return initial } let tail = Array(array.dropFirst()) return tailRecursive(array: tail, initial: eachOperation(head, initial), eachOperation: eachOperation) } tailRecursive(array: array, initial: 0, eachOperation:{(element: Int, answer: Int)->Int in element + answer }) ➔ 47
  • 17.
    extension Array { functailRecursive<Result>( _ initial: Result, eachOperation: (Result, Element) -> Result ) -> Result { guard let head = self.first else { return initial } let tail = Array(self.dropFirst()) return tail.tailRecursive(eachOperation(initial, head), eachOperation: eachOperation) } } array.tailRecursive(0, eachOperation: + ) array.tailRecursive(0) { (element: Int, answer: Int) -> Int in return element + answer } array.reduce(0) { (element: Int, answer) -> Int in return element + answer }
  • 18.
  • 19.
    • . • . ->. -> ex) -> .
  • 20.
    func searchTopViewController(viewController: UIViewController?)-> UIViewController? { guard let viewController = viewController else { return nil } switch viewController { case let viewController as UITabBarController: return searchTopViewController(viewController: viewController.selectedViewController) case let viewController as UINavigationController: return searchTopViewController(viewController: viewController.viewControllers.last) case let viewController where viewController.presentedViewController != nil: return searchTopViewController(viewController:viewController.presentedViewController) default: return viewController } }
  • 21.