【问题标题】:Python Runtime Error not working as expectedPython 运行时错误未按预期工作
【发布时间】:2019-11-04 11:59:52
【问题描述】:

我有一个输入文件如下

3
01
0010100
11011

输出应该是这样的

LIVES
DIES
LIVES

但是我的代码返回,

DIES
[1, 0]
DIES
[0, 1, 0, 0, 0, 1, 0]
DIES
[1, 1, 0, 1, 1]

我正在解决这个问题 (https://open.kattis.com/problems/whowantstoliveforever)。基本上,我正在查看位置 i-1 和 i+1 的位的当前值(如果它们存在;否则假设它们为 0)。如果我的程序恰好看到一个 1,那么第 i 位的下一个值为 1,否则为 0。所有位同时更改,因此下一个状态的新值仅取决于前一个状态的值.如果宇宙只包含零,它就是死的。

我想说如果程序捕获到无限循环,这可能意味着宇宙将继续存在,0 和 1 会不断重复。如果len(set(x)) 为 1,那么我将返回 False。

import sys


def get_bit(bits, i):
    if 0 <= i < len(bits):
        return int(bits[i])
    else:
        return 0


def print_result(boolean):
    print("LIVES" if boolean else "DIES")


def recursion(in_list, output_list):
    try:
        for index in range(len(in_list)):
            if (get_bit(in_list, index-1) == 0 and get_bit(in_list, index+1) == 0) or (get_bit(in_list, index-1) == 1 and get_bit(in_list, index+1) == 1):
                output_list.append(0)
            elif(get_bit(in_list, index-1) == 0 and get_bit(in_list, index+1) == 1) or (get_bit(in_list, index-1) == 1 and get_bit(in_list, index+1) == 0):
                output_list.append(1)
        if len(set(output_list)) == 1:
            return False
        else:
            in_list = output_list
            output_list = []
            recursion(in_list, output_list)
    except RuntimeError:
        return True


num_cases = int(sys.stdin.readline().strip())
for i in range(num_cases):
    _list = []
    case = sys.stdin.readline().strip()
    for char in case:
        _list.append(char)
    output_list = []
    print_result(recursion(_list, output_list))
    print(output_list)

如果不是except RuntimeError 不起作用,有什么办法可以解决这个问题?

【问题讨论】:

  • 请在问题本身中解释您的问题。
  • @Blorgbeard 谢谢,更新了。
  • 好的,尝试根据递归限制错误来检测是错误的方法。您需要跟踪以前的状态并检测何时进入您已经看到的状态。如果发生这种情况,您就知道存在循环或稳定(非死)状态。
  • 而且不要递归,重构回迭代。
  • @Blorgbeard 当我尝试迭代时,我认为很难确切知道何时停止。

标签: python python-3.x python-2.7 error-handling runtime-error


【解决方案1】:

由于某些原因,依赖递归限制并不理想。但主要是“如果它存在 X 代,那么它可能永远存在”的算法从根本上不会削减它以获得更长的输入。

这是我如何实现它的框架:

def get_new_state(old_state):
    pass # todo: implement

def is_dead(state):
    pass # todo: implement

def determine_fate(state):
    seen = set()       
    while True:
        if is_dead(state):
            return "DIES"
        if state in seen:
            return "LIVES"
        seen.add(state)
        state = get_new_state(state)

我正在使用一个集合来记住旧状态。如果我们不止一次地看到一个状态,那么我们就遇到了一个循环或一个稳定状态,所以我们知道结果是“LIVES”。如果这在我们达到空状态之前没有发生,那么我们知道结果是“DIES”。

请注意,您必须改变使用列表来表示状态,因为列表不可散列,因此无法添加到集合中。我会使用字符串。

【讨论】:

  • 我不认为“如果它为2**len(input) 世代而存在,那么它永远存在”有什么问题......
  • 是的,如果您将限制设置为该方法有效的最大状态数。我仍然不会滥用递归限制来计算状态!
【解决方案2】:

首先,@Blorgbeard 是对的,不要这样做。这是一个可怕的反模式。


但是要回答您的名义问题:即使在小情况下您的 sn-p 也不起作用的原因是您进行递归的方式:

recursion(in_list, output_list)

如果宇宙存在,那么在某些时候这确实会抛出一个RuntimeError(更准确地说是RecursionError),因为它超出了递归限制(不是很大;在我的测试环境中是2961,所以不要'不期望它能正确解决任何大型实例)。这意味着此调用的某些实例将返回True。但是,该返回值是看不见的,并且封闭函数结束时没有返回任何内容,这意味着它返回None。

要正确捕获RecursionError,请将try-catch 块从递归函数中取出,或者将您想要的任何值传递到堆栈中,如下所示:

return recursion(in_list, output_list)

这为您给出的小案例提供了正确的返回值。


不过,您真正应该做的是认识到您还不知道解决此问题的有效算法(问题陈述允许在每个输入案例中最多包含 200000 个字符)。因此,您应该打印特定输入经过的所有状态,并寻找模式。

这个问题可能对你来说太难了,如果你认为编程练习对你来说更重要,你应该放弃它,或者在互联网上找到算法的描述。再说一遍,它不需要任何算法知识(除了递归等基本知识),也不需要任何数学知识(除了奇偶校验等基本知识),所以它是一个很好的练习。

【讨论】:

    猜你喜欢
    • 2019-11-07
    • 2019-06-20
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-09
    • 2021-08-04
    • 1970-01-01
    相关资源
    最近更新 更多