似乎无法弄清楚此递归在哪里中断

时间:2018-12-18 02:40:24

标签: python recursion puzzle

This is for Advent of Code, Day 17. 基本上,您有一个从y = 0向下流动的“容器”和“水”的图。(水压力不适用。)您应该弄清楚到了多少个网格单元将成为“水”。完成了它可以到达的所有容器的填充。

我实际上让它几乎在五分钟内工作了,但是它不会终止... 在一天的大部分时间里,我一直在弄乱它,但仍然无法弄清楚。在每行之后放置print语句以监视正在发生的事情(尝试过PythonTutor,但是您必须像五分钟一样滚动才能看到输出,特别是对于长的递归代码,每次迭代后都有点烦人)。 然后尝试在几乎每一行和每个循环内推回收益。依然没有 ... 我讨厌递归看起来多么简单,但是然后您就开始困惑自己了(至少我这样做了……) 现在,我只是感到疲倦和困惑。 任何帮助表示赞赏。

coor = [(495, 2), (495, 3), (495, 4), (495, 5), (495, 6), (495, 7), (495, 7), (496, 7), (497, 7), (498, 7), (499, 7), (500, 7), (501, 7), (501, 3), (501, 4), (501, 5), (501, 6), (501, 7), (498, 2), (498, 3), (498, 4), (506, 1), (506, 2), (498, 10), (498, 11), (498, 12), (498, 13), (504, 10), (504, 11), (504, 12), (504, 13), (498, 13), (499, 13), (500, 13), (501, 13), (502, 13), (503, 13), (504, 13)]

cx, cy = zip(*coor)
minx, maxx = min(cx), max(cx)
miny, maxy = min(cy), max(cy)

water = []

def flow(water, pt):
  if pt not in water:
    water.append(pt)
  x,y = pt
  if y < maxy:
    while (x, y+1) not in coor:
      if y+1 > maxy:
        return
      plotW(water)
      water.append((x,y+1))
      y += 1

    collect(water, (x, y))
  else:
    return


def collect(water, pt):
  x,y = pt
  if minx <= x <= maxx and y < maxy:
    i = x - 1
    j = x + 1

    # fills container half to the left of the stream
    while (i, y) not in coor:
      if y >= maxy: break
      plotW(water)
      if (i, y+1) in coor or (i, y+1) in water:
        if (i, y) not in water:
          water.append((i, y))
          i -= 1
      else:
        flow(water, (i, y))
        break

    # fills container half to the right of the stream
    while (j, y) not in coor:
      if y >= maxy: break
      plotW(water)
      if (j, y+1) in coor or (j, y+1) in water:
        if (j, y) not in water:
          water.append((j, y))
          j += 1
      else:
        flow(water, (j, y))
        break

    collect(water, (x, y-1))

def plotW(water):
  wx, wy = zip(*water)

  fig = plt.figure(figsize = (2,2.5))
  plt.xlim(minx-1, maxx+1)
  plt.ylim(miny-1, maxy)
  plt.scatter(cx, cy, marker = 's', color = 'r')
  plt.scatter(wx, wy)
  plt.gca().invert_yaxis()
  plt.axes().set_aspect('equal', 'datalim')
  plt.show()

flow(water, (500, 0))

最后几个步骤如下所示: (本应在第二张图片处停止) enter image description here

1 个答案:

答案 0 :(得分:2)

  

让它几乎在五分钟内工作了,但是它不会终止

我已将其修改为通过更严格地监视y坐标来终止(在您描述的阶段)。您必须根据自己的工作来决定这些更改是否有意义:

import matplotlib.pyplot as plt

coordinates = [
    (495, 2), (495, 3), (495, 4), (495, 5), (495, 6), (495, 7), (495, 7), (496, 7),
    (497, 7), (498, 7), (499, 7), (500, 7), (501, 7), (501, 3), (501, 4), (501, 5),
    (501, 6), (501, 7), (498, 2), (498, 3), (498, 4), (506, 1), (506, 2), (498, 10),
    (498, 11), (498, 12), (498, 13), (504, 10), (504, 11), (504, 12), (504, 13),
    (498, 13), (499, 13), (500, 13), (501, 13), (502, 13), (503, 13), (504, 13)
]

cx, cy = zip(*coordinates)
min_x, max_x = min(cx), max(cx)
min_y, max_y = min(cy), max(cy)

water = []

def flow(water, point):
    if point not in water:
        water.append(point)
        plotW(water)

    x, y = point

    if y < max_y:
        while (x, y + 1) not in coordinates:
            if y + 1 > max_y:
                return y

            water.append((x, y + 1))
            plotW(water)
            y += 1

        y = collect(water, (x, y))

    return y

def collect(water, point):
    x, y = point

    if min_x <= x <= max_x and y < max_y:
        i, j = x - 1, x + 1

        # fills container half to the left of the stream
        while (i, y) not in coordinates:
            if y >= max_y:
                break

            plotW(water)

            if (i, y + 1) in coordinates or (i, y + 1) in water:
                if (i, y) not in water:
                    water.append((i, y))
                    i -= 1
            else:
                _ = flow(water, (i, y))
                break

        # fills container half to the right of the stream
        while (j, y) not in coordinates:
            if y >= max_y:
                break

            plotW(water)

            if (j, y + 1) in coordinates or (j, y + 1) in water:
                if (j, y) not in water:
                    water.append((j, y))
                    j += 1
            else:
                y = flow(water, (j, y))
                break

        if y < max_y:
            y = collect(water, (x, y-1))

    return y

def plotW(water):
    wx, wy = zip(*water)

    plt.figure(figsize=(2, 2.5))
    plt.xlim(min_x - 1, max_x + 1)
    plt.ylim(min_y - 1, max_y)
    plt.scatter(cx, cy, marker='s', color='r')
    plt.scatter(wx, wy)
    plt.gca().invert_yaxis()
    plt.axes().set_aspect('equal', 'datalim')
    plt.show()

flow(water, (500, 0))