【问题标题】:Python - finding all paths between points of arbitrary shapePython - 查找任意形状点之间的所有路径
【发布时间】:2016-11-29 20:44:53
【问题描述】:

我的计划目标如下:

给定任何形状(表示为枚举点及其与其他点的连接),返回一个包含所有可能路径列表(作为字符串/列表/...)。路径是给定形状的“绘图”,其中:

  • 没有连接被使用不止一次
  • “笔”尚未提起(示例如下)。
  • 以下代码基本上是我到目前为止所提出的。这不是实际程序的代码,但基本语义是相同的(即如果这段代码可以工作,我的程序也可以工作)。

    """
    Example used:
    
        2
       / \
      /   \
     /     \
    1-------3
    """
    
    
    from copy import deepcopy
    
    points = {1: [2,3],
              2: [1,3],
              3: [1,2]}
    
    def find_paths(prev_point, points):
        for current_point in points[prev_point]:
            points[current_point].remove(prev_point)
            points[prev_point].remove(current_point)
            return [prev_point] + find_paths(current_point, points)
        return [prev_point]
    
    def collect(points):
        results = []
        for first_point in points:
            result = find_paths(first_point, deepcopy(points))
            results.append(result)
        return results
    
    print(collect(points))
    

    我一直在努力让它返回所有路径。到目前为止,它只列出了 3 个(共 6 个)。我确实知道问题是由于f 中的for-loop 每次被调用时只执行一次(并且它被调用3 次),因为每次执行都由return 终止。但是,到目前为止,我一直未能找到避免这种情况的方法 - 我尝试将 f 设为生成器,但这给了我一个生成器列表作为最终结果,无论我如何尝试更改它。

    感谢您的帮助!

    编辑:生成器版本我只是用yield s 替换了find_paths 中的returns。 所以最后两行看起来像:

    ... yield [prev_point] + find_paths(current_point, points) yield [prev_point]

    此外,我为生成器使用了一个“扁平化器”,但它根本不起作用:

    def flatten(x): if callable(x): for i in x: yield flatten(i) yield x

    定义函数(): 产量 1 lis = [1,2,func]

    对于 f in flatten(lis): 打印(f)

    【问题讨论】:

    • 如果这不是家庭作业,你确定没有图书馆可以做这个吗?如果是家庭作业,那么实际上提供你迄今为止所做的工作并提出比“你能为我做这个”更好的问题。
    • for current_point in points[prev_point]:... points[prev_point].remove(current_point) 迭代时不要从其中删除。我建议复制一份:for current_point in points[prev_point][:]。其次,您使用生成器的想法听起来不错,向我们展示代码,我们将告诉您如何修复它。但首先尝试简单地将生成器转换为列表,这很容易。
    • 我看到的一个问题是您的递归 find_paths 函数没有“结束条件”。您需要知道何时停止。此外,您的 find_paths 无法返回“多条路径”,这似乎是预期的。
    • @daveydave400 Tbh 我没有寻找图书馆,因为我想自己做一个空闲时间项目(不是为了学校;))另外,我认为你的意思是 return [prev_point],如果 points 字典为“空”则运行。
    • 如果您正在四处寻找有关此问题的信息,它看起来像是柯尼斯堡七桥的变体

    标签: python generator nodes graph-theory


    【解决方案1】:

    我认为以下工作。我基于您的原始代码,但做了一些事情(有些是必要的,有些不是):

    1. 重命名find_paths 中的参数,以便对我更有意义。我们正在使用current_point 而不是previous_point 等。
    2. 添加结束条件以停止递归。
    3. 为正在生成的每条可能路径制作点的副本,并返回(生成)每条可能的路径。您的原始代码对此没有逻辑,因为每次调用 find_paths 时它只期望一个结果,但是在使用这样的递归时这并没有真正意义。出于同样的原因,我也extend我的最终结果。

    代码如下:

    from copy import deepcopy
    
    points = {1: [2,3],
              2: [1,3],
              3: [1,2]}
    
    
    def find_paths(current_point, points):
        if len(points[current_point]) == 0:
            # End condition: have we found a complete path? Then yield
            if all(not v for v in points.values()):
                yield [current_point]
        else:
            for next_point in points[current_point]:
                new_points = deepcopy(points)
                new_points[current_point].remove(next_point)
                new_points[next_point].remove(current_point)
                paths = find_paths(next_point, new_points)
                for path in paths:
                    yield [current_point] + path
    
    
    def collect(points):
        results = []
        for first_point in points:
            result = find_paths(first_point, points)
            results.extend(list(result))
        return results
    
    print(collect(points))
    

    结果:

    [1, 2, 3, 1]
    [1, 3, 2, 1]
    [2, 1, 3, 2]
    [2, 3, 1, 2]
    [3, 1, 2, 3]
    [3, 2, 1, 3]
    

    您的原始示例图片应使用以下内容:

    points = {
        1: [2,3],
        2: [1,3,4,5],
        3: [1,2,4,5],
        4: [2,3,5],
        5: [2,3,4],
        }
    

    编辑:删除了我在collect 中的额外深度副本。

    每次都必须复制points,因为您正在“保存”您正在“绘制”的当前路径的当前状态。如果你没有复制它,那么沿着路径到节点 2 会在沿着路径到节点 3 时改变点的状态。

    【讨论】:

    • 非常感谢!!为什么需要对原始 points 进行深度复制呢?坦率地说,我根本没想到这会奏效
    • 它可能不是,只是复制代码的产物....编辑:已修复
    猜你喜欢
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    • 1970-01-01
    相关资源
    最近更新 更多