Reputation: 409
Is there any quick way to find out, if two points on 2D boolean area are connected and you can mobe only up, down, left and right on a square with value True? Let's say you would have following 6x6 2D list:
In code, that would be:
bool2DList = [6][6]
bool2DList = { True, True, False, False, True, True,
False, True, True, False, True, True,
False, True, True, False, False, True,
False, False, False, False, False, True,
False, False, False, False, True, True,
False, True, True, True, True, True }
Green squares have value True and blue ones False. I was thinking about function( it would probably need to be recursive ), in which you would put a 2D list as a argument alongside with a list of tuples ( coordinates ) of several points and finaly one tuple of special point, it could have header like this:
def FindWay( bool2DList,listOfPoints,specialPointCoord )
In this example the special point would be the point P with coordinates 5;1. Let's imagine you would start walking from that special points. What points could you reach without stepping on the blue squares? In this example, only points P4 and P5 ( the output could be let's say the coordinates of those points, so 0;5 and 5;3 ). It would probably need to be recursive, but I have no idea, how the body should look like.
Thank you.
Upvotes: 0
Views: 1177
Reputation: 2600
Here is an option how you can code it:
A = np.array([[0, 1, 1, 0], [1, 0, 1, 1], [1, 0, 1, 0], [0, 1, 0, 0]]).astype(bool)
print A
[[False True True False]
[ True False True True]
[ True False True False]
[False True False False]]
We can upgrade standard dfs function for our needs:
def dfs_area(A, start):
graph = {}
res = np.zeros_like(A)
for index, x in np.ndenumerate(A):
graph[index] = x
visited, stack = set(), [start]
while stack:
vertex = stack.pop()
x, y = vertex[0], vertex[1]
if vertex not in visited and graph[vertex] == True:
visited.add(vertex)
if x < A.shape[0]-1:
stack.append((x+1, y))
if x > 1:
stack.append((x-1, y))
if y < A.shape[1]-1:
stack.append((x, y+1))
if y > 1:
stack.append((x, y-1))
res[tuple(np.array(list(visited)).T)] = 1
return res
Assume that we want points connected to (1, 2) - second row, third value:
mask = dfs_area(A, (1,2))
>> mask
array([[0, 1, 1, 0],
[0, 0, 1, 1],
[0, 0, 1, 0],
[0, 0, 0, 0]])
Upvotes: 1
Reputation: 77847
I'm afraid there is no trivial way to do this. It's a graph traversal problem, and Python doesn't have built-in functions supporting that. I expect that you'll want a simple implementation of a breadth-first graph search.
Very briefly, you keep a list of nodes you've visited, but not handled; another list of nodes you've handled. The steps look like this:
handled = [] visited = [P] while visited is not empty: remove a node A from the visited list for each node B you can reach directly from A: if B is new (not in visited or handled list): put B on the visited list put A on the handled list
This will find all nodes you can reach. If you're worried about a particular node, then inside the loop, check to see whether B is your target node. When you put B on the visited list, put it on the front for depth-first, on the back for breadth-first.
In this application, "all the nodes you can reach" consists of the bordering ones with the same Boolean label.
Upvotes: 5