从字符串

时间:2018-05-19 18:40:12

标签: python recursion

  

编写一个程序,确定将句点添加到十进制字符串的位置,以便生成的字符串是有效的IP地址。可能有多个有效的IP地址对应一个字符串,在这种情况下,您应该打印所有可能性。例如,"19216811",九个可能的IP地址中的两个包括192.169.1.119.216.81.1

以下是我的(不完整)解决方案:

def valid_ips(string):
  def is_valid_part(part):
    return len(part) == 1 or (part[0] != 0 and int(part) <= 255)  

  def build_valid_ips(substring):
    result = []
    for i in range(1, min(4, len(substring))):
      part = substring[:i]
      if is_valid_part(part):
        for sub in build_valid_ips(substring[i:]):
          result.append(part + '.' + sub)
    return result

  return build_valid_ips(string)

这是我正在编写的书中的一个变体问题,所以我没有解决方案。但是,我有几个问题

  • 此解决方案不正确,因为它总是返回一个空列表,但我不知道为什么。好像我正在处理归纳步骤和基本情况。有人能指出我正确的方向吗?
  • 我怎样才能做得更好?我理解每个递归调用都会生成一个新列表和多个新字符串,这会增加大量开销,但是如何避免这种情况呢?

2 个答案:

答案 0 :(得分:1)

您的函数始终返回一个空列表,因为您从不在递归的底层向result附加任何内容。

build_valid_ips中,只有在循环访问从result的递归调用获得的值时,才会附加到build_valid_ips,但这只会返回通过循环进一步递归调用build_valid_ips获得的值。 1}}。在某个地方递归必须停止,但在这个级别,没有任何东西被附加。因此,没有任何东西可以传递回递归。

尝试添加行

    if is_valid_part(substring):
        result.append(substring)
<{1}}中的

,就在build_valid_ips行之后。然后,您应该发现您的代码会返回一个非空列表。

然而,结果仍然不正确。您的代码中没有任何地方强制要求IP地址必须包含四个部分,因此代码将生成错误的输出,例如result = []。我将由你来修改你的代码以解决这个问题。

至于如何改进代码,这更像是Code Review的问题。对于像你这样的小例子,它永远不会运行很长时间,我不会太担心生成太多的列表和字符串。只有在代码性能出现问题时才会担心这些问题。

答案 1 :(得分:-1)

鉴于IP必须包含四个不同的部分,您可以使用递归来生成分组的可能性列表:

s = "19216811"
def ips(d, current = []):
  if not d:
     yield current
  else:
     for i in range(1, len(s)):
       yield from ips(d[i:], current + [d[:i]])

final_ips = list(filter(lambda x:all(len(i) > 1 for i in x[:2]), [i for i in ips(s) if len(list(filter(None, i))) == 4]))
new_ips = ['.'.join(a) for i, a in enumerate(final_ips) if a not in final_ips[:i]]

输出:

['19.21.6.811', '19.21.68.11', '19.21.681.1', '19.216.8.11', '19.216.81.1', '19.2168.1.1', '192.16.8.11', '192.16.81.1', '192.168.1.1', '1921.68.1.1']