计算字符串

时间:2017-10-08 08:50:26

标签: python recursion divide-and-conquer

我一直在努力解决这个问题。这就是问题所在:

  

给定描述电路的字符串,计算总电阻   电路。

以下是一个例子:

  • 输入:3 5 S
  • 预期输出:8

字符串中的操作数由运算符跟踪,表示电阻是串联还是并联。但是让我们分析一个更复杂的电路:

  • 输入:3 5 S 0 P 3 2 S P
  • 预期输出:0

一步一步:

  1. 输入开头的3 5 S给出了8,因此第一个中间步骤是字符串8 0 P 3 2 S P
  2. 8 0 P给我们0,因为一个电阻被短路,因此我们得到0 3 2 S P
  3. 3 2 P5
  4. 最后0 5 P0
  5. 这是我的尝试。我尝试使用递归,因为它似乎是一个可以通过这种方式解决的问题。首先我写了一个辅助函数:

    def new_resistance(a,b,c):
    if c == '':
        if int(a) == 0 or int(b) == 0:
            return 0
        else:
            return 1/(1/int(a) + 1/int(b))
    else:
        return int(a) + int(b)
    

    计算电路新电阻的函数:

    def resistance(array):
    if isinstance(array, int):
        return array
    else:
        if isinstance(array,list):
            temp = array
        else:
            temp = array.split(" ")
        i = 0
        while True:
            try:
                a = new_resistance(temp[i], temp[i+1], temp[i+2])
            except Exception as e:
                i += 1            
            if len(temp[i+3:]) == 0:
                return resistance(new_resistance(temp[i], temp[i+1], temp[i+2]))
            else:
                return resistance(temp[:i] + [new_resistance(temp[i], temp[i+1], temp[i+2])] + temp[i+3:])
    

    程序背后的想法是从列表的开头开始计算列表前三个元素的阻力,然后将它们附加到新列表的开头(没有三个元素)并调用再次使用新列表运行。这样做直到只剩下一个整数并返回整数。

    感谢任何帮助。

    更新:

    问题的解决方案,使用类似于NPR解析器的堆栈和解析器。

    operator_list = set('PS')
    
    def resistance(circuit):
      temp = circuit.split(" ")
      stack = []
      for char in temp:
          if char in operator_list:
              a = new_resistance(stack.pop(), stack.pop(), char)
              print(a)
              stack.append(a)
          else:
              print(char)
              stack.append(char)
      return stack[-1]
    
    def new_resistance(a,b,c):
      if c == 'P':
          if float(a) == 0 or float(b) == 0:
              return 0
          else:
              return 1/(1/float(a) + 1/float(b))
      else:
          return float(a) + float(b)
    
    circuit = '3 5 S 0 P 3 2 S P'
    resistance(circuit)
    
    # 3
    # 5
    # 8.0
    # 0
    # 0
    # 3
    # 2
    # 5.0
    # 0
    

4 个答案:

答案 0 :(得分:2)

您的计划,或者更具体地说是您的parser,似乎依赖于Reverse Polish NotationRPN又是Normal Polish Notation的一个小变体。简单地说,Normal Polish Notation是一个抽象表示,其中算术表达式的运算符跟随他们的操作数,不像运算符之前的{{1}} 他们的操作。基于此表示的解析器可以通过使用堆栈轻松实现(通常不需要解释括号)。

如果您的任务是开发该解析器,您可以从我上面链接的维基百科文章中获得一些输入。

答案 1 :(得分:2)

问题是,一旦到达0 3 2 S P,就不能简单地采用前3个元素。您需要在字符串中的任何位置查找number number S_or_P

您可以使用正则表达式执行此任务:

import re

circuit = '3 5 S 0 P 3 2 S P'

pattern = re.compile('(\d+) +(\d+) +([SP])')

def parallel_or_serie(m):
  a, b, sp = m.groups()
  if sp == 'S':
    return str(int(a) + int(b))
  else:
    if a == '0' or b == '0':
      return '0'
    else:
      return str(1/(1/int(a) + 1/int(b)))

while True:
  print(circuit)
  tmp = circuit
  circuit = re.sub(pattern, parallel_or_serie, circuit, count=1)
  if tmp == circuit:
    break

# 3 5 S 0 P 3 2 S P
# 8 0 P 3 2 S P
# 0 3 2 S P
# 0 5 P
# 0

请注意1 1 P将输出0.5。您可以将int替换为float并修改正则表达式以解析浮点数。

答案 2 :(得分:0)

首次认可RPN的@none的信用。

我想起了旧的记忆。我在20世纪80年代在8位计算机上使用FORTH语言。好的,回到Python:

circuit = '3 5 S 0 P 3 2 S P'

stack = []
for n in circuit.split():
    if n == 'S':
        r1 = stack.pop()
        r2 = stack.pop()
        stack.append(r1+r2)
    elif n == 'P':
        r1 = stack.pop()
        r2 = stack.pop()
        stack.append(0.0 if (r1 == 0 or r2 == 0) else 1/(1/r1+1/r2))
    else:
        stack.append(float(n))

assert len(stack) == 1    
print(stack[0])

答案 3 :(得分:0)

  1. 本着 VPfB 的精神,针对串并联的任意组合(不仅是成对)

     def calculateresistor(dataString):
     stack = []
     r = []
     cicuit=dataString
     for n in circuit.split():
         if n == 'S':
             stackSize=size(stack)
             if size(stack)>=2:
                 for k in range(0,size(stack)-1):
                     r.append(float(stack.pop()))
                     r.append(float(stack.pop()))
                     stack.append((r[-1]+r[-2]))
         elif n == 'P':
             stackSize=size(stack)
             if size(stack)>=2:
                 for k in range(0,size(stack)-1):
                     r.append(float(stack.pop()))
                     r.append(float(stack.pop()))
                     r.append(0.0 if (r[-1] == 0 or r[-2] == 0) else (1/(1/r[-1]+1/r[-2])))
                     stack.append(r[-1])
         else:
             stack.append(float(n))
     assert len(stack) == 1
     return(stack)