【问题标题】:Need help getting this recursive function working需要帮助让这个递归函数工作
【发布时间】:2020-09-08 20:34:30
【问题描述】:

我有一个对象 person,它在位置 x, y 定义了一个人

class Person:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return "Person({}, {})".format(self.x, self.y)

    # creates a duplicate of Person at a new x, y -> x_new, y_new
    def next(self, x_movement, y_movement):
        # this is not how the actual movement is calculated, but works for demonstration
        return Person(self.x + x_movement, self.y + y_movement)

我希望为这个人找到所有可能的动作,t_steps 未来。 可能的运动由一个数组限定(在任何给定时间可能不同,因此这是一个示例)。

x_possible = [-1, 0, 1] 注意:在另一个代码运行期间,它可能是 [3, 5, 2, 4] 所以算法需要使用这个数组来知道可能的运动。

y_possible = [-1, 0, 1]

方法调用是这样的:

initial_person = Person(0, 0)
# all possible movements for person, 3 time steps into the future
all_possible_movements_for_person = get_possible_movements(initial_person , 3)

get_possible_movements 方法必须返回一个元组数组,其中每个元组的结构如下:

(
x_new = FIRST movement of x from this branch of movements,
y_new = FIRST movement of y from this branch of movements,
next Person from the initial_person --> person_2 = initial_person.next(x_new, y_new),
next Person from the person_2       --> person_3 =       person_2.next(x_possible[i] , y_possible[j],
.
.
will have a person count equal to t_step from the method call
)

example:
initial_person = Person(0, 0)
# all possible movements for person, 3 time steps into the future
all_possible_movements_for_person = get_possible_movements(initial_person , 3)
all_possible_movements_for_person contains a large array of tuples with first entry:

# I am showing the movements made on the person in the tuple for example
(-1, -1, person(-1,-1), person2(-1,-1), person3(-1,-1))
- first element is 1 because the algorithm should pick the first x_movement to be -1 based on the
possible movements array.
- second is -1 for the same reason with y movements.
- the first person in the array is from doing the operation initial_person.next(-1,-1)
- the second person in the array is from doing the operation person1.next(-1,-1)
- the third person in the array is from doing the operation person2.next(-1,-1)


following similar logic, the next tuple in the output array would be:
(-1, -1, person(-1,-1), person2(-1,-1), person4(-1,0))
the person 4 object is new and is the next entry in the y_movements array to get that person.
then
(-1, -1, person(-1,-1), person2(-1,-1), person5(-1,1))
(-1, -1, person(-1,-1), person2(-1,-1), person6(0,-1))
(-1, -1, person(-1,-1), person2(-1,-1), person7(0,0))

输出看起来像example,但请记住,我使用字符串来表示此输出示例中的对象。

我的尝试就在这里......我不擅长递归。

x_possible = [-1, 0, 1]
y_possible = [-1, 0, 1]


class Person:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return "Person({}, {})".format(self.x, self.y)

    # creates a duplicate of Person at a new x, y -> x_new, y_new
    def next(self, x_movement, y_movement):
        # this is not how the actual movement is calculated, but works for demonstration
        return Person(self.x + x_movement, self.y + y_movement)

def get_possible_movements(c, n):
    locs = []
    get_people_recursion(c, n, n, 0, 0, locs, ())
    return locs


def get_people_recursion(person, i, time_step, a_index, b_index, locs, tup):
    if time_step < 0:
        locs.append(tup)
        return

    if a_index >= len(x_possible) or b_index >= len(y_possible):
        return

    if time_step == i:
        tup += (x_possible[a_index], y_possible[b_index])

    c_next = person.next(x_possible[a_index], y_possible[b_index])
    tup += (c_next,)

    get_people_recursion(c_next, i, time_step-1, a_index, b_index, locs, copy.deepcopy(tup))
    get_people_recursion(c_next, i, time_step, a_index + 1, b_index, locs, copy.deepcopy(tup))

all_people = get_possible_movements(Person(0, 0), 1)
print(len(all_people))
for i in all_people:
    print(i)

输出:

(-1, -1, Person(-1, -1), Person(-2, -2))
(-1, -1, Person(-1, -1), Person(-2, -2), Person(-2, -3))
(-1, -1, Person(-1, -1), Person(-2, -2), Person(-2, -3), Person(-1, -4))
(-1, -1, Person(-1, -1), 0, -1, Person(-1, -2), Person(-1, -3))
(-1, -1, Person(-1, -1), 0, -1, Person(-1, -2), Person(-1, -3), Person(0, -4))
(-1, -1, Person(-1, -1), 0, -1, Person(-1, -2), 1, -1, Person(0, -3), Person(1, -4))

可能有帮助也可能没有帮助的图表...https://prnt.sc/sliwcx

【问题讨论】:

  • 我真的不明白这个问题,确切地说。什么是“C”?你能更清楚地解释一下这样做的目的吗?预期的输出是巨大的,所以也许一个输入 -> 逻辑 -> 输出的简单示例会使正在发生的操作更加明显。你必须使用这个C 类和递归吗?看起来像是某种产品逻辑,可能最好使用 itertools。感谢您的澄清。
  • 类 C 只是一个带有 a 和 b 的对象。如果需要,可以在笛卡尔图上将其称为 x 和 y。然后调用 C.next(ai,bi) 会将该图上的 C“移动”到新位置 ai,bi。然后从该方法返回一个新的 C。我想一个很好的可视化方法是我们试图在图表上获取所有可能的“结束”位置,从 initial_C 开始。我们希望保持从 C_initial 的初始移动,即元组中的前两个数字。元组中的其他 C 都是用于创建到该位置的路径的所有 C。
  • 另请注意,C 的可能“移动”限制在 a_possible 和 b_possible 的范围内。这些不是 x 和 y 方向,而是完全定义 C 的“运动”的其他东西
  • 如果您描述您要解决的真正问题以及您提出的解决方案,我们可以更好地回答您的问题。
  • 正在重写以使其更加清晰。

标签: python python-3.x recursion depth-first-search


【解决方案1】:

您的代码很接近。匹配字符串输出的技巧是保留一个 count 变量来构建结果字符串或使用静态类变量来计算 id。

除此之外,递归遍历并推送/弹出堆栈以存储路径。其他的都是products

这是代码。

import itertools

class Person:
    def __init__(self, n, a, b):
        self.n = n
        self.a = a
        self.b = b

    def __repr__(self):
        return f"Person{self.n}"

def produce_c(a, b, n):
    combos = list(itertools.product(a, b))
    count = 0

    def explore(pair, path=[]):
        nonlocal count
        count += 1
        path.append(Person(count, *pair))

        if len(path) == n:
            yield tuple(path)
        else:
            for pair in combos:
                yield from explore(pair, path)

        path.pop()

    for pair in combos:
        for path in explore(pair):
            yield (*pair, *path)

if __name__ == "__main__":
    for x in produce_c([-1, 0, 1], [-1, 0, 1], 3):
        print(x)

【讨论】:

  • 你更接近于理解我的想法。我们需要元组中的对象,因为它们将在程序的后面部分使用。该程序非常庞大且令人困惑,因此我尝试将其拆分出来以显示我们的问题。我还整理了这张图,以准确显示我在这里需要什么。我们还需要 C,因为它是一个具有许多功能的较大对象。我只是剥离了所有内容以使其更简单。谢谢您的帮助! prnt.sc/slhysk
  • 没问题。我添加了一个类并修复了一个错误,但它是相同的算法。它闻起来有点过于简单了——这可能是xy problem。生成这些东西很容易,但为什么呢?如果这只是一个随机练习,那很酷,但我怀疑它是某些搜索问题或游戏的一部分,可能有更好的方法。
  • 如果你可以看一下,我完全重做了介绍
  • 好的。除了更改类名之外,这个算法似乎仍然基本上可以满足您的需求,不是吗?如果没有,如果您不介意让我知道我错过了什么,我可以轻松适应。
  • 你太棒了!不完全是我需要的,但足够接近我想通了。在此处对您的脚本进行一些修改:justpaste.it/4hb8c。此外,我需要 Person 类中的下一个 def,因为在我的实际代码中,两者之间的关系基于在下一个方法中执行的一些计算和算法。跨度>
猜你喜欢
  • 2020-07-04
  • 2017-09-22
  • 2015-02-11
  • 2011-02-25
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多