这个函数如何计算?

时间:2016-11-27 23:56:08

标签: function return swift3

我一直在使用CodeWars katas,我遇到了一个非常酷的解决方案,有人提出了。我遇到的问题是我不明白它是如何工作的。我理解其中的一些内容就像它通常做的那样,但不是详细的细节。它回归了吗?它是如何进行计算的?有人可以向我解释这个,因为我真的要学习如何做到这一点。如果您知道我可以阅读或观看的任何其他资源,那将会有所帮助。我在Swift文档中没有看到这样的内容。

    func findDigit(_ num: Int, _ nth: Int) -> Int {
           let positive = abs(num)

           guard nth > 0 else { return -1 }
           guard positive > 0 else { return 0 }
           guard nth > 1 else { return positive % 10 }

           return findDigit(positive / 10, nth - 1) }        

对于上下文:

说明

函数findDigit将两个数字作为输入,num和nth。它输出num的第n位数(从右到左计数)。

请注意

如果num为负数,请忽略其符号并将其视为正值。 如果第n个不是正数,则返回-1。 请记住,42 = 00042.这意味着findDigit(42,5)将返回0.

实施例

findDigit(5673,4)返回5

findDigit(129,2)返回2

findDigit(-2825,3)返回8

findDigit(-456,4)返回0

findDigit(0,20)返回0

findDigit(65,0)返回-1

findDigit(24,-8)返回-1

非常感谢任何帮助。感谢。

4 个答案:

答案 0 :(得分:1)

这是一个简单的递归函数。递归意味着它一遍又一遍地调用自身,直到满足结束递归的条件。如果条件永远不会满足,你最终会得到一个无限的递归,这不是一件好事:)

正如您已经了解该功能的目的,以下是其内部工作原理的详细信息:

// Saves the absolute value (removes the negative sign) of num
let positive = abs(num)

// Returns -1 if num is 0 or negative
guard nth > 0 else { return -1 } 

// Returns 0 if the absolute value of num is 0 (can't be negative)
guard positive > 0 else { return 0 } // Could be guard positive == 0

// nth is a counter that is decremented with every recursion.
// positive % 10 returns the remainder of positive / 10
// For example 23 % 10 = 3
// In this line it always returns a number from 0 - 9 IF nth <= 0
guard nth > 1 else { return positive % 10 }

// If none of the above conditions are true, calls itself using
// the current absolute value divided by 10, decreasing nth.
// nth serves to target a different digit in the original number
return findDigit(positive / 10, nth - 1) 

让我们一步一步地完成一个例子:

findDigit(3454, 3)
num = 3454, positive = 3454, nth = 3
-> return findDigit(3454 / 10, 3 - 1)

num = 345, positive = 345, nth = 2 // 345, not 345.4: integer type
-> return findDigit(345 / 10, 2 - 1)

num = 35, positive = 35, nth = 1
-> return 35 % 10
-> return 5

答案 1 :(得分:0)

这是一种递归解决方案。它本身并没有返回,它本身就是一个更简单的案例,直到它到达一个基本案例(这里是一个1位数字)。例如,让我们在第一个示例中查看它的作用: findDigit(5673,4)来电 findDigit(567,3)来电 findDigit(56,2)来电 findDigit(5,1),它是返回5的基本情况,它一直回到表面。

答案 2 :(得分:0)

这是一种递归算法。它的工作原理是通过将原始问题同时缩小为较小的问题来解决原始问题,然后递归地解决它,直到基本情况被击中。

如果您看到正在进行的通话,我认为您将更容易理解它。当然,最好在调试器中逐步完成,以便真正了解正在发生的事情。我已将感兴趣的部分编号在下面引用它们

func findDigit(_ num: Int, _ nth: Int) -> Int {
    print("findDigit(\(num), \(nth))") //#1
    let positive = abs(num) // #2

    guard nth > 0 else { return -1 } // #3
    guard positive > 0 else { return 0 } // #4
    guard nth > 1 else { return positive % 10 } // #5

    return findDigit(positive / 10, nth - 1) // #6
}

print(findDigit(5673, 4))
  1. 我打印出函数及其参数,你能看到发生了什么。这是打印的内容:

      

    findDigit(5673,4)

         

    findDigit(567,3)

         

    findDigit(56,2)

         

    findDigit(5,1)

         

    5

  2. num的正值,因此-符号不会妨碍。

  3. 断言nth变量大于0。由于此问题中的数字计数,任何等于less 0的值都无效。在这种情况下,返回-1在Swift中这是非常糟糕的做法。这是Optionals的存在。最好让此函数返回Int?并返回nil来表示nth变量中的错误。

  4. 断言positive变量大于0.唯一的另一种可能情况是positive为0,在这种情况下,其数字(对于任何位置)为{{1} },这就是为什么你有0

  5. 断言return 0大于nth。如果不是这种情况,那么1必须为1(编号为nth的警卫确保它不能为负数,或#3。在这种情况下,第一个数字十进制数的位置是以10为模的数字,因此返回0的原因。

  6. 如果我们到达这一行,我们知道我们的第n个{positive % 10)的理智值不是> 0,而且我们的正数大于0。现在我们可以通过递归来解决这个问题。我们会将10分为正数,并将其设为新的1,我们将减少nth,因为此次调用的nth数字将在{ {1}}下次通话的地点。

答案 3 :(得分:0)

CodeWars上有一位名叫JohanWiltink的人回答了我的问题。但我选择接受尼古拉斯的细节。

这是JohanWiltink的解释:

该函数不会将其自身返回为函数;它使用不同的参数调用自身并返回该递归调用的结果(这可能是嵌套的,在这种情况下,nth = 1)。

findDigit(10,2)因此返回findDigit(1,1)的值。

如果您还没有看到这是如何运作的,请尝试手动锻炼,例如findDigit(312,3)将返回。

非常感谢所有回答的人!真的很感激!