Home > database >  How do I output the quickest path of a maze via backtracking?
How do I output the quickest path of a maze via backtracking?

Time:05-28

I'm trying to solve a backtracking problem in python. Not only should my code be able to identify and reach the goal, but also output the quickest path to it. The maze is looks like this:

xxxxxxx
xSx   x
x xx  x
x     x
xxxx  x
x     x
x xx xx
x E   x
xxxxxxx 

Start [1,1]
End   [7,2]

The backtrack function I wrote so far, looks as follows:

def find_escape(rN, cN, route=[]):
    route.append([rN, cN])
    if is_escape(rN, cN):
        return route
    else:
        escapeRoutes = []
        relCoordinates = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        for relN in relCoordinates:
            absN = [rN   relN[0], cN   relN[1]]
            if is_free(absN[0], absN[1]) and absN not in route:
                temp = find_escape(absN[0], absN[1], route)
                if len(temp) > 0:
                    escapeRoutes.append(temp)
        if len(escapeRoutes) > 0:
            min = escapeRoutes[0]
            for i in escapeRoutes:
                if len(i) < len(min):
                    min = i
            return min
        else:
            return []

My problem is, that the output shows no path but rather every single coordinate he "walked" through in chronological order:

Output:
[[2, 1], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [4, 5], [5, 5], [5, 4], [6, 4], [7, 4], [7, 5], [7, 3], [7, 2], [5, 3], [5, 2], [5, 1], [6, 1], [7, 1], [4, 4], [2, 5], [2, 4], [1, 4], [1, 5], [1, 3], [1, 1]]

The assisting functions "is_escape" and "is_free" are simple. So no issue there.

CodePudding user response:

try to always pass the copy of the route recursively. That works for me. Otherwise the function adds every field that the algorithm enters to the original route and the fields that do not belong to the best route are never removed from the route again. If you only pass a copy of the route you never change the original route but only the respective copy of the recusion pass. And there each copy contains a possible route independent of the other tried routes. Then the shortest route is returned without containing the other fields of the other routes.

def find_escape(rN, cN, route=[]):
    route.append([rN, cN])
    if is_escape(rN, cN):
        return route
    else:
        escapeRoutes = []
        relCoordinates = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        for relN in relCoordinates:
            absN = [rN   relN[0], cN   relN[1]]
            if is_free(absN[0], absN[1]) and absN not in route:
                temp = find_escape(absN[0], absN[1], route.copy())
                if len(temp) > 0:
                    escapeRoutes.append(temp)
        if len(escapeRoutes) > 0:
            min = escapeRoutes[0]
            for i in escapeRoutes:
                if len(i) < len(min):
                    min = i
            return min
        else:
            return []

CodePudding user response:

It is generally a bad idea to use a non primitive default value like [] because you can get strange behavior. It will not create a fresh value on each execution of the function like you expect, but re-use the same array call-to-call.

Try running this code to see what I mean:

def router(route=[]):
    route.append("a")
    return route

print(router()) # "['a']"
print(router()) # "['a', 'a']"

You might naively expect it to print "['a']" both times, but the second time prints "['a', 'a']", because the array was not made fresh.

Instead, set your default arg to None, and inside the function check if it's None and replace it with an array if so:

def router(route=None):
    if route == None:
        route = []
    route.append("a")
    return route

print(router()) # "['a']"
print(router()) # "['a']"
  • Related