简体   繁体   English

这个算法中的Python尾递归优化?

[英]Python tail recursion optimization in this algo?

I got the following problem: Let's consider the following encoding table:我遇到了以下问题:让我们考虑以下编码表:

0 -> A
1 -> B
2 -> C
...
  • input: string containing a list of integers输入:包含整数列表的字符串
  • output: int representing the number of words that can be encoded from the input输出:int 表示可以从输入中编码的单词数
  • examples:例子:
"0" -> 1 (word is A)
"10" -> 2 (words are BA and K)
"121" -> 3 (words are BCB, MB and BV) 

I wrote this algo我写了这个算法

import string
sys.setrecursionlimit(100)  # limit the number of recursions to 100
# {0: 'a', 1: 'b', etc.}
dict_values = dict(zip(range(26), string.ascii_lowercase))

def count_split(list_numbers: list) -> int:
    if len(list_numbers) == 0:
        return 0

    elif len(list_numbers) == 1:
        return 1

    elif len(list_numbers) == 2:
        if int(list_numbers[0]) == 0:
            return 1

        elif 10 <= int("".join(list_numbers)) <= 25:
            return 2

        else:
            return 1

    else:  # list_numbers contains at least three elements
        if count_split(list_numbers[:2]) == 2:
            return count_split(list_numbers[1:]) + count_split(list_numbers[2:])

        else:
            return count_split(list_numbers[1:])

def get_nb_words(code: str) -> int:
    return count_split(list(code))

# print(get_nb_words("0124")) -> 3
# print(get_nb_words("124")) -> 3
# print(get_nb_words("368")) -> 1
# print(get_nb_words("322")) -> 2
# print(get_nb_words("12121212121212121212")) -> 10946

Surprisingly, this algo works on the last example "12121212121212121212" .令人惊讶的是,该算法适用于最后一个示例"12121212121212121212" I expected the number of recursions to be exceeded because at each step, the function count_split is called twice on a list.我预计会超过递归次数,因为在每个步骤中,函数count_split在列表中被调用两次。 Thus, the number of calls is much more than 100 (even more than 1000) !这样一来,调用次数就远远超过100次(甚至超过1000次)!

In the meanwhile I found this post on stackoverflow saying that tail recursion is not optimized in Python, so I'm a bit suprised !与此同时,我在 stackoverflow 上发现这篇文章说尾递归没有在 Python 中优化,所以我有点惊讶!

Could someone explain to me why the recursion limit is not exceed in this algorithm ?有人可以向我解释为什么在这个算法中没有超过递归限制吗?

You care about the recursion depth, ie the maximum depth (height?) of the call stack.您关心递归深度,即调用堆栈的最大深度(高度?)。

Here's an empirical approach: (code that measures the depth)这是一种经验方法:(测量深度的代码)

import string, sys
sys.setrecursionlimit(100)  # limit the number of recursions to 100

dict_values = dict(zip(range(26), string.ascii_lowercase))
stack = []
max_depth = 0
def count_split(list_numbers: list) -> int:
    global max_depth
    stack.append(None)
    max_depth = max(max_depth, len(stack))
    if len(list_numbers) == 0:
        return 0

    elif len(list_numbers) == 1:
        return 1

    elif len(list_numbers) == 2:
        if int(list_numbers[0]) == 0:
            return 1

        elif 10 <= int("".join(list_numbers)) <= 25:
            return 2

        else:
            return 1

    else:  # list_numbers contains at least three elements
        if count_split(list_numbers[:2]) == 2:
            stack.pop()
            result = count_split(list_numbers[1:]) + count_split(list_numbers[2:])
            stack.pop(); stack.pop()
            return result

        else:
            result = count_split(list_numbers[1:])
            stack.pop()
            return result

def get_nb_words(code: str) -> int:
    return count_split(list(code))

print(get_nb_words("12121212121212121212"))
print(max_depth) # 20

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM