I'm working through a problem (using python) that asks me to do the following:
Starting from (0,0) and facing North in a \mathbb{Z} x \mathbb{Z} grid, and given a sequence of 'moves' (R for right, L for left, and F for forward by 1), what will be the final position of a particle assuming we can only move by 1's in the horizontal and vertical directions. For example, moves = 'RFRL' will put us at (1,0)
The difficulty I am having on getting started with this problem is that I don't know how to represent a "turn". An 'F' in the 'moves' will mean adding +-1 to the y coordinate depending if the particle is facing North or South, and +-1 to the x coordinate depending if the particle is facing East or West.
You just need to split the task into subtasks. You need to implement an operation of turning, and operation of going forward, with respect to where you're currently facing. For example, you can do like this.
def turn_right(current_direction):
next_direction_map = {'N':'E', 'E':'S', 'S':'W', 'W':'N'}
return next_direction_map[current_direction]
def turn_left(current_direction):
next_direction_map = {'N':'W', 'W':'S', 'S':'E', 'E':'N'}
return next_direction_map[current_direction]
def forward(current_position, current_direction):
x, y = current_position
if current_direction == 'N':
return (x, y+1)
elif current_direction == 'S':
return (x, y-1)
elif current_direction == 'E':
return (x+1, y)
elif current_direction == 'W':
return (x-1, y)
facing_direction = 'N'
current_position = (0, 0)
facing_direction = turn_right(facing_direction)
current_position = forward(current_position, facing_direction)
facing_direction = turn_right(facing_direction)
facing_direction = turn_left(facing_direction)
print(current_position, facing_direction)
Notice that using a dictionary I can tell with just 1 line where I'll be turning. A similar dictionary approach could be used in forward function too, but I'm afraid it would look scary (with lambdas stored inside the dictionary).
Now you're only left with reading the path string (RFRL), iterating over it with a loop, and calling an appropriate method on the current facing direction and current position. This I left for you (for educational purposes)
Related
I am trying to apply an effective divide and conquer approach on a 2D array that is sorted row-wise, and column-wise. Starting from the bottom left cell in the matrix, my algorithm chooses either to move one cell up or one cell to right depending on whether k is > or < than the curr_cell. However, I keep getting an error of list_indices out of range when I run this code. I'd like some help in debugging this.
The following is my code:
def KeyFinder(k, matrix, x, y):
curr_cell = matrix[x][y] #starting at bottom left corner
if k == curr_cell:
return curr_cell
else:
if curr_cell < k:
KeyFinder(k, matrix, x-1, y) #if target is less than value, it must be above us so move one up
else:
KeyFinder(k, matrix, x, y+1) #otherwise, move one right
var = KeyFinder(20, [[1,4,7,11], [8,9,10,20], [11,12,17,30]], 2, 0)
print(var)
For the error that you see, you have to check the bounds in both direction, not to go out of your matrix.
However, aprart from that your implementation has other issues like when you are calling you function recursively you are not returning the answer.
I did fix it like this:
def KeyFinder(k, matrix, x, y):
m, n = len(matrix) , len(matrix[0]) # get you dimentions
curr_cell = matrix[x][y] #starting at bottom left corner
if k == curr_cell:
return curr_cell
if curr_cell > k and (0 < x) :
return KeyFinder(k, matrix, x-1, y) #if target is less than value, it must be above us so move one up
elif (y < n - 1) :
return KeyFinder(k, matrix, x, y+1) #otherwise, move one right
var = KeyFinder(20, [[1,4,7,11], [8,9,10,20], [11,12,17,30]], 2, 0)
print(var)
I did not change the way you wrote to be easy for you to see the changes, however, when you get the dimension you can as well set the starting point inside the function, not in the call
Ok, lets sum it up quickly. You search for the number 20 in the 3x4 array, it goes like that.
Start at matrix [2][0] = 11.
20>11, so move to [1][0] = 8.
20>8, so move to [0][0] = 1.
20>1, so move to [-1][0]
and there is your mistake, you cant reach index=-1 in an array.
I wrote some code to make a terrain generation algorithm, and it takes "forever" to run. I managed to trace the issue back to a breadth first search algorithm that I made, and more specifically, these first 4 if statements that check if the current cell's neighbors are valid spots to move to. The rest of the function is because I have multiple searches going at the same time exploring different areas and I delete one of them if two touch.
for self.x, self.y in self.active:
# Fix from here
if grid[self.x][self.y-1] == 1 and (self.x,self.y-1) not in self.searched:
self.searched.append((self.x,self.y-1))
self.nextActive.append((self.x,self.y-1))
if grid[self.x+1][self.y] == 1 and (self.x+1,self.y) not in self.searched:
self.searched.append((self.x+1,self.y))
self.nextActive.append((self.x+1,self.y))
if grid[self.x][self.y+1] == 1 and (self.x,self.y+1) not in self.searched:
self.searched.append((self.x,self.y+1))
self.nextActive.append((self.x,self.y+1))
if grid[self.x-1][self.y] == 1 and (self.x-1,self.y) not in self.searched:
self.searched.append((self.x-1,self.y))
self.nextActive.append((self.x-1,self.y))
# to here it takes 0.00359s * about 1000 cycles
self.active = self.nextActive[:]
self.nextActive = []
if self.active == []:
self.full = True
return
for i in self.active:
for searcher in breathClassList:
if searcher == self: continue
if i in searcher.searched:
if len(self.searched) >= len(searcher.searched):
breathClassList.remove(searcher)
elif self in breathClassList: breathClassList.remove(self)
break
if anyone has any suggestions to make this run faster, I am all ears.
It looks like self.searched is a list (as you're calling append on it). Looking for an item in a list will take time proportional to the length of the list in the worst case (that is the time complexity is O(n), where n is the length).
One thing you could do is make that list a set instead, because looking up an item happens in constant time (i.e. is constant as the number of items grows. Time complexity is O(1)). You can do this here, because you're storing tuples and those are immutable and therefore hashable.
Along with the answer from ndc85430, I would create the deltas for the search inside a separate array and loop this array to do updates. This will avoid the code repetition nicely (note using add here instead of append to show using sets instead.).
deltas = ((0, -1), (1, 0), (-1, 0), (0, 1))
for self.x, self.y in self.active:
for dx, dy in deltas:
x, y = self.x + dx, self.y + dy
if grid[x][y] == 1 and (x, y) not in self.searched:
self.searched.add((x, y))
self.nextActive.add((x, y))
Let's say you have the grid:
list = [[-,O,-,-,O,-,],
[O,-,-,-,-,O],
[O,O,-,-,X,-],
[-,-,O,-,-,-]]
How would you get the coordinates of all O's that are within a distance of 3 from X?
From what I saw in other answers, using scipy.spatial.KDTree.query_ball_point seemed like a common approach but I was unable to figure out how to adapt it to my use case. One possible idea I had was to store every coordinate of the list such as
coords=[[0,0],[0,1]...] and then use the scipy method and pass in the coordinate of the X and the searching distance. And then once I received the list of possible coordinates, I then iterate through the list and check which ones are equal to O. I was wondering, however, if there was a more efficient or more optimized solution I could use. Any help would be greatly appreciated.
You don't need to make it too complicate by using Scipy. This problem can easily done by help of mathematics.
Equation of coordinate inside circle is x^2 + y^2 <= Radius^2, so just check coordinate that inside the circle.
list = [[-,O,-,-,O,-,],
[O,-,-,-,-,O],
[O,O,-,-,X,-],
[-,-,O,-,-,-]]
X_coor = #Coordinate of X, in this case y = 2, x = 4
d = #Maximum distance from X in this case d = 3
total = 0
O_coor = [] #Store coordinate of all O near X
for y in range(max(0, X_coor.y - d), min(list.length - 1, X_coor.y + d)):
for x in range(max(0, X_coor.x - sqrt(d**2 - (y - X_coor.y)**2)), min(list.length - 1, X_coor.x + sqrt(d**2 - (y - X_coor.y)**2))):
if list[y][x] == "O":
total++
O_coor.append([x, y])
print(total)
print(O_coor)
It a long code, but you can ask me parts that you don't understand.
Note: This solution check only coordinate in circle area not entire list, so even if you have large list this still very fast.
I'm writing a python script to get the southwestern vertex of the selected object, and get its coordinates X, Y and Z.
Logically the southwestern point would match the vertex having the minimum X, Y and Z. How can I access theses values in python?
So far I've been able to get the min XYZ values of the object, but it's resulting the bounding box values which is not the expected result. Instead I need the vertex values.
Can someone guide me through?
from pymxs import runtime as rt
aSelect = rt.selection[0]
minX = aSelect.min.x
minY = aSelect.min.y
minZ = aSelect.min.z
'Southwestern' point is kinda open to interpretation (for example, I don't see the Z in the name), for the sake of argument let's pick the two most likely - one that gets the vertex that's furthest away from the object max, and one that get the vertex with the smallest total of x+y+x coords:
from pymxs import runtime as rt
obj = rt.selection[0]
mesh = rt.snapshotAsMesh(obj)
minDiagonalVert = max(list(mesh.verts), key=lambda vert: rt.distance(vert.pos, obj.max))
minTotalVert = min(list(mesh.verts), key=lambda vert: vert.pos.x + vert.pos.y + vert.pos.z)
rt.delete(mesh)
Quite obviously, this will work only for some kind of meshes, but that's up to you to set your own criteria that you want to match in that case.
Thank you so much Swordslayer, it helped me to understand how to access the vertices informations.
Yes you're right 'southwestern' doesn't necessarily includes the Z, but implicitely I need the Z with the lowest value and this min Z should equal 0 for my purpose.
Anyway, now I was able to play around and it perfectly fit my needs, using these values to move the pivot position to this southwestern point of my object:
from pymxs import runtime as rt
from operator import itemgetter
anchor = rt.point3(0,0,0)
if len(rt.selection) == 0:
print('no object selected! please select one object')
elif len(rt.selection) > 1:
print('too much objects selected! please select one object')
else:
aSelect = rt.selection[0]
mesh = rt.convertToMesh (aSelect)
vertices = list(mesh.verts)
positions = []
for i in range(len(vertices)):
positions.append(vertices[i].pos)
positions = sorted(positions, key=itemgetter(2,1,0))
minX = positions[0][0]
minY = positions[0][1]
minZ = positions[0][2]
anchor = rt.point3(minX,minY,minZ)
aSelect.pivot = anchor
print('anchor set # minX: {}, minY: {}, minZ: {}'.format(minX,minY,minZ))
I'm writing a simple A* algorithm for finding the shortest path. But I need something more complicated. The agent can only go forward and rotate(90 deg). Will it influence at path or I can use simple A*?
Thanks for all.
def astar(maze, start, end):
start_node = Node(None, start)
start_node.g = start_node.h = start_node.f = 0
end_node = Node(None, end)
end_node.g = end_node.h = end_node.f = 0
open_list = []
closed_list = []
open_list.append(start_node)
while len(open_list) > 0:
current_node = open_list[0]
current_index = 0
for index, item in enumerate(open_list):
if item.f < current_node.f:
current_node = item
current_index = index
open_list.pop(current_index)
closed_list.append(current_node)
if current_node == end_node:
path = []
current = current_node
while current is not None:
path.append(current.position)
current = current.parent
return path[::-1]
children = []
for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0), (-1, -1), (-1, 1), (1, -1), (1, 1)]:
node_position = (current_node.position[0] + new_position[0], current_node.position[1] + new_position[1])
if node_position[0] > (len(maze) - 1) or node_position[0] < 0 or node_position[1] > (len(maze[len(maze)-1]) -1) or node_position[1] < 0:
continue
if maze[node_position[0]][node_position[1]] != 0:
continue
new_node = Node(current_node, node_position)
children.append(new_node)
for child in children:
for closed_child in closed_list:
if child == closed_child:
continue
child.g = current_node.g + 1
child.h = ((child.position[0] - end_node.position[0]) ** 2) + ((child.position[1] - end_node.position[1]) ** 2)
child.f = child.g + child.h
for open_node in open_list:
if child == open_node and child.g > open_node.g:
continue
open_list.append(child)
The main issue here is that the A* algorithm needs to be made aware of the fact that there's a difference between "being at position (x, y) facing in direction d1" and "being at position (x, y) facing in direction d2." If the algorithm doesn't know this, it can't give you back the best series of instructions to follow.
One way that you can solve this is to imagine that your world isn't a 2D grid, but actually a 3D space consisting of four copies of the 2D grid stacked on top of one another. Just as your position in the 2D space consists of your current (x, y) coordinate, your position in the 3D space consists of your current (x, y) coordinate, combined with the direction that you're facing.
Imagine what it means to move around in this space. You have two options for the action you can take - "move" or "turn 90°" The "move" action will move you one step forward in the current 2D slice you're in, where "forward" has a different meaning based on what slice you're in. In other words, "move" will cause you to move purely within the X/Y plane, keeping your direction fixed. The "turn" operation will keep your X/Y position fixed, but will change which plane that you're in (based on which direction you happen to be facing at the time).
If you encode this information explicitly into your search, then A* can use it to find the best path for you to take. You'll need to define some new heuristic that estimates the distance to the goal. One option would be to assume there are no walls and to determine how many steps you'd have to take, plus the number of rotations needed, to get to the goal. At that point, A* can give you the best path to follow, using your heuristic to guide its search.
More generally, many problems of the form "I have a position in the world, plus some extra state (orientation, velocity, etc.)" can be converted from pathfinding in 2D space to pathfinding in 3D space, where your third dimension would be that extra piece of information. Or perhaps it'll go up to 4D or 5D space if you have multiple extra pieces of information.
Hope this helps!
The first thing to do is to divide the sourcecode into two functions: the forward model of the agent and the (path)planning algorithm itself. In the forward model, it's specified, that the agent has three possible actions (forward, rotleft, rotright). The A* planner creates the gametree for the agent. A possible sequence is: left, forward, forward.
It's not a classical pathplanning problem but an AI planning problem. Realizing such a two layer system is more complicated over a normal A* wayfinding algorithm, because the rotation action doesn't bring the agent nearer to the goal. It's more complicated to decide, if a simulated action has improved the situation or was a step backward.
In a real life scenario, even the described separation into forward model and planner wouldn't solve the issue, because the state space in a map would be grow very fast. Additional heuristics are needed to guide the A* planner into the optimal direction.