【问题标题】:Remove the parentheses around the very first element in an expression tree and in each of its sub-expression trees in Python在 Python 中删除表达式树及其每个子表达式树中第一个元素周围的括号
【发布时间】:2017-08-27 21:39:22
【问题描述】:

目标是实现简化操作:删除表达式树及其每个子表达式树中第一个元素周围的括号,其中表达式作为包含在各种括号中的字符串输入给出。这必须适用于任意数量的括号,例如:

(12)3((45)6) -> 123(45​​6),去掉12左右的括号,然后去掉45左右

((12)3)4(((5)67)8) -> 1234(5678),去掉 12 周围的括号,然后是 123,然后是 5,然后是 567。不要去掉 5678 周围的括号,因为那样是第二个元素。

我该怎么做?

编辑:到目前为止,我所拥有的是:

def simplify(expression):
    """
    call itself recursively until no consecutive parentheses exist
    """
    result = []
    consec_parens = 0
    inside_nested = False
    for char in expression:
        if char == ')' and inside_nested:
            inside_nested = False
            consec_parens = 0
            continue
        if char == '(':
            consec_parens += 1
        else:
            consec_parens = 0
        if consec_parens == 2:
            inside_nested = True
        else:
            result.append(char)
    result = ''.join(result)
    if result == expression:
        return result
    return simplify(result)

它适用于嵌套括号数至少为两个的所有情况,但它不适用于头部,即对于 (AB)C,它不会删除 AB 周围的括号。但是,对于 ((AB)C),它会删除 AB 周围的括号,从而得到 (ABC)。

【问题讨论】:

  • 查看以上更改
  • 如果您的代码适用于除顶级案例之外的所有情况,您可以通过将表达式包装在一对括号中(如果还没有的话)来简单地解决它。
  • @user7034701:在你看来,你能告诉我什么是极端情况吗?我为这个问题实现了我的逻辑。它通过了您在问题中提到的所有示例。但是我仍然无法在其中一个在线提交中通过一个测试用例。我也无法获得有关该测试用例的足够详细信息。你有没有想过你认为在这里可能会失败的测试用例?它给了我正确的结果测试用例,如((AB)C)、(AB)C、(12)3((45)6)、((12)3)4(((5)67)8)。对于您在上面的问题中提到的这些测试用例,我得到了相同的结果。

标签: python algorithm tree expression


【解决方案1】:

这可以被视为一个有限状态机(具有三个状态),您在每个级别实例化一次,其中每个( 符号创建一个新级别。或者,它是一个确定性的pushdown automaton,具有两个微不足道的状态(一个进行中状态和一个完成状态,我们都没有显式建模)和三个堆栈符号,每个代表当前级别的机器状态:

  • 之前 - 我们进入关卡后立即所处的状态。遇到除) 之外的任何字符都会转换到其他状态。
  • Inside - 需要移除的括号内的状态。在之前中通过遇到( 输入。
  • 完成 - 处理当前关卡时我们所处的状态。这意味着要么我们已经删除了一组括号,要么我们不需要,因为第一个元素没有包含在其中。

此外,遇到( 会将一个新符号推入堆栈,模拟进入新关卡,) 从中弹出一个符号,模拟从关卡离开。当 Before → Inside 和 Inside → Doneexcept /strong> 发生转换。

以下代码是上述内容到 Python 的简单翻译:

from enum import Enum

class State(Enum):
    Before = 0
    Inside = 1
    Done   = 2

def simplify(expression):
    levels = [State.Before]
    result = []

    for c in expression:
        if c == '(':
            if levels[-1] == State.Before:
                levels[-1] = State.Inside
            else:
                result.append(c)
            levels.append(State.Before)
        elif c == ')':
            levels.pop()
            if levels[-1] == State.Inside:
                levels[-1] = State.Done
            else:
                result.append(c)
        else:
            if levels[-1] == State.Before:
                levels[-1] = State.Done
            result.append(c)

    return ''.join(result)

测试上面的,我们得到:

>>> simplify('(12)3((45)6)')
'123(456)'
 >>> simplify('((12)3)4(((5)67)8)')
'1234(5678)'
>>> simplify('(AB)C')
'ABC'
>>> simplify('((AB)C)')
'ABC'

【讨论】:

  • 根据规则,((((ABC)))) 应该如何评估?
  • @CodeHunter 很难说。根据规则,这甚至是一个有效的表达式吗?由于ABC 是唯一的元素(从树的根部看),那么所有这些额外的括号在它周围做什么?表达式代表哪棵树?我猜如果有的话,它应该评估为ABC。
  • 感谢您的澄清。是的,这实际上是有道理的。所以,一般来说,AB 可以在一个括号内,而不是很多。如果它在多个括号下,实际上是没有任何意义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
  • 1970-01-01
相关资源
最近更新 更多