编写一个程序,确定将句点添加到十进制字符串的位置,以便生成的字符串是有效的IP地址。可能有多个有效的IP地址对应一个字符串,在这种情况下,您应该打印所有可能性。例如,
"19216811"
,九个可能的IP地址中的两个包括192.169.1.1
和19.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)
这是我正在编写的书中的一个变体问题,所以我没有解决方案。但是,我有几个问题
答案 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']