Python - 查找任意形状的点之间的所有路径

时间:2016-11-29 20:44:53

标签: python generator nodes graph-theory

我对该计划的目标如下:

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

  • 没有连接多次使用
  • '笔'没有解除(例如下面的例子)。
  • animation of a house being drawn as described above

    以下代码基本上是我到目前为止所提出的。它不是实际程序的代码,但基本语义是相同的(即如果这个代码可以工作,我的程序也会工作)。

    """
    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个)。我确实理解这个问题来自for - f循环每次调用时都被执行一次(并且它被调用3次),因为执行被终止了每次return。但是,到目前为止我还没有找到避免这种情况的方法 - 我玩了f一个生成器,但这给了我一个生成器列表作为最终结果,无论我怎么试图改变它

    感谢任何帮助!

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

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

    另外,我玩弄了一个' flattener'对于发电机,但它根本不起作用:

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

    def func(): yield 1 lis = [1,2,func]

    for f in flatten(lis): print(f)

    1 个答案:

    答案 0 :(得分:0)

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

    1. 重命名current_point中的参数以使我更有意义。我们正在使用previous_point而不是find_paths
    2. 添加结束条件以停止递归。
    3. 为每个可能生成的路径制作一个点的副本,并返回(产生)每个可能的路径。你的原始代码没有这个逻辑,因为每次调用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)) 我的最终结果。
    4. 以下是代码:

      [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中的额外深层检查。

      每次都需要复制elements { border-left: black solid 1px; } elements:nth-child(1) { border-left: none; } ,因为您正在“保存”当前路径的“绘图”状态。如果你没有复制它,那么沿着通往节点2的路径下去将改变点到达节点3的路径时的状态。