I am writing a little game in which many (order 1000-10000) cars are driving around you and need to dodge each other smoothly. Their position can be represented by their 2D XY-coordinates.
Each frame, every car needs to ensure it doesn't bump into another one, which naively implemented would be an O(N^2) algorithm. What is the best 2D acceleration structure I can employ to make this more efficient?
To add some more context:
Since cars can move anywhere, the structure needs to constantly keep track of all cars. So it needs to be quick to update (not O(N) for each car for example).
Every car moves on every frame
Cars are not allowed to hit any other car. They obviously have knowledge of their own size, and their current direction and speed. Their size is none-zero (cause you know, it's a car), and it needs this data in collision checks.
I considered a regular grid with set-structure, which works, but each car still has to check its own cell and all its (8) neighbours, so I imagine there are still better ways.
So, you've to check if there is a collision. For there to be a collision if I understand your example, there have to be two cars in the same spot after the cars move.
I think we can use the concept of spot, or position, here. You could save the positions that at a given time have a car on them in a set (coordinates of a matrix, or whatever suits your problem best). When a car moves, delete it's position from the set and insert it's new one to the set.
Once we've this, you'll only have to check if the set contains a car's next position to know if there will be a collision or not, and in a HashSet consulting that is O(1). Apply that to your number of cars(n) and you'll do your collision management in O(n).
Example for further clarification:
You've this matrix of positions with cars on "O"s and empty spaces on "X"s. Meaning you'd have a car on position 1 and another one in position 8 if you number your positions from the top left corner.
O X X
X X X
X O X
This would imply you've a set of Integers with positions 1 and 8 on it. Now, an example to move one of the cars:
Car on position 1 moves to position 2: You check if position 2 is in the set[O(1)]. It isn't. You remove position 1 from the set[O(1)] and add position 2 to the set[O(1)], because now position 1 doesn't have a car on it but position 2 does.
Repeat for every car (n) => O(1) * O(n) = O(n).
You could use something like a quadtree. A quadtree is a 2D indexing scheme with O(log n) update (insert/remove) time.
The easiest possibility is to store rectangles (axis aligned bounding boxes) for each car. Then, each time before you reinsert a car at it's new position, you perform a window query (query for a rectangle) at the new position to see whether it overlaps with any other car. If you have the source code of the tree you can even implement a combined operation updateAnCheck() that detects collisionas and updates in a single call. (I assume that the structure is updated often enough that old and new position overlap, so that collisions are more or less reliably detected, other wise cars could 'teleport' through one another if they are fast enough).
Complexity:
Update: O(log n) per car
Query: O(log n) per car
Space: About O(log n) per car
Total computational complexity: detecting all collisions for n car: O(n * 2 * log n) = O(n log n)
Total space complexity: about O(n * log n)
There are many open source implementations for quadtrees available, if you are using Java, you may want to check out mine.
Related
I was in an interview and I was asked to create an efficient algorithm to the following problem:
Input:
We have a List of RGB colors. Every color represented by 3 coordinate <x,y,z> between 0 to 255. This list never change.
We are getting every time some additional color (not necessarily from the list above) and we need to return the closest (in term of distance) color from the list to the additional color.
Notes:
We can do some pre-processing on the colors's list because the list never change.
Distance between colors defined as:
d = ((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2)^1/2
Example:
Let: List: {<1,1,1>,<1,0,1>,<2,2,2>,<0,1,0>}
Additional color: <0,0,0>
Result: The minimal distance to <0,0,0> is <0,1,0>.
My attempt to solve this:
Obviously we can do pre-processing and to keep all the color pairs in the world and to save the distance as well and we can get the solution in O(1) run time but with huge memory (255^3*n)
The most naive solution is to loop over the list and to calculate the distance between every color from the list to the additional color and to return the color with the minimum distance. It's taking O(n) where n is the length of the color list.
I tried to maybe to do some sort the list with x,y,z coordinate and keeping 3 sorted list or sort by distance to <0,0,0> but I don't have a clue how to continue with it.
I also saw this but the question is not about the algorithmic approach to the problem.
Precomputing a full lookup table is not so unthinkable nowadays. As long as you have less than 256 reference colors, the required array has 256³ (not 255³) entries, which is 17 MB. (The double for 65536 colors.) But you really need good reasons to use such a device.
If the number of colors is reasonable, the naive solution is quite acceptable.
For larger number of colors (say from 10 up), several practical solutions are possible:
a kD-tree (where k=3); query time close to O(Log N);
an octree; query time close to O(Log N) if the colors are not clustered;
a grid (for instance 4096 cells of size 16); query time O(N), but in lucky cases, the asymptotic constant can be made very small.
The tools of computational geometry might suggest a 3D Voronoi diagram combined to a locator in a 3D subdivision, but these are sophisticated and pretty hard to implement, even though they will support a guaranteed O(Log N) query time.
I would personally favor a kD-tree.
I have an array of coordinates, i.e each index contains (x,y) coordinates. I want to figure out that if any of the coordinates are in single row or column. The challenge is to do in a single loop where M is the length of the array. I have been trying hard but cant seem to do it without using two loops. Just need help with the algorithm.
Edit: Basically the problem is that I have M pieces on an N by N board. Each piece can move any vertically and horizontally by any number. Just want to figure out that if any piece can attack any other piece.
This is element distinctness/uniqueness problem that has complexity O(MLogm) in common case (i.e. sorting).
If there are no memory limitations, you can use hash tables for Y and X coordinates, in this case single run through array solves the problem
Edit: For limited board it is simpler to use boolean array length N for horizontals and verticals. Time complexity O(M), memory consumption O(N)
for every rook:
if Horiz[rook.Y] then
two rooks share horizontal
if Vert[rook.X] then
two rooks share the same vertical
Horiz[rook.Y] = True
Vert[rook.X] = True
Grid Illumination: Given an NxN grid with an array of lamp coordinates. Each lamp provides illumination to every square on their x axis, every square on their y axis, and every square that lies in their diagonal (think of a Queen in chess). Given an array of query coordinates, determine whether that point is illuminated or not. The catch is when checking a query all lamps adjacent to, or on, that query get turned off. The ranges for the variables/arrays were about: 10^3 < N < 10^9, 10^3 < lamps < 10^9, 10^3 < queries < 10^9
It seems like I can get one but not both. I tried to get this down to logarithmic time but I can't seem to find a solution. I can reduce the space complexity but it's not that fast, exponential in fact. Where should I focus on instead, speed or space? Also, if you have any input as to how you would solve this problem please do comment.
Is it better for a car to go fast or go a long way on a little fuel? It depends on circumstances.
Here's a proposal.
First, note you can number all the diagonals that the inputs like on by using the first point as the "origin" for both nw-se and ne-sw. The diagonals through this point are both numbered zero. The nw-se diagonals increase per-pixel in e.g the northeast direction, and decreasing (negative) to the southwest. Similarly ne-sw are numbered increasing in the e.g. the northwest direction and decreasing (negative) to the southeast.
Given the origin, it's easy to write constant time functions that go from (x,y) coordinates to the respective diagonal numbers.
Now each set of lamp coordinates is naturally associated with 4 numbers: (x, y, nw-se diag #, sw-ne dag #). You don't need to store these explicitly. Rather you want 4 maps xMap, yMap, nwSeMap, and swNeMap such that, for example, xMap[x] produces the list of all lamp coordinates with x-coordinate x, nwSeMap[nwSeDiagonalNumber(x, y)] produces the list of all lamps on that diagonal and similarly for the other maps.
Given a query point, look up it's corresponding 4 lists. From these it's easy to deal with adjacent squares. If any list is longer than 3, removing adjacent squares can't make it empty, so the query point is lit. If it's only 3 or fewer, it's a constant time operation to see if they're adjacent.
This solution requires the input points to be represented in 4 lists. Since they need to be represented in one list, you can argue that this algorithm requires only a constant factor of space with respect to the input. (I.e. the same sort of cost as mergesort.)
Run time is expected constant per query point for 4 hash table lookups.
Without much trouble, this algorithm can be split so it can be map-reduced if the number of lampposts is huge.
But it may be sufficient and easiest to run it on one big machine. With a billion lamposts and careful data structure choices, it wouldn't be hard to implement with 24 bytes per lampost in an unboxed structures language like C. So a ~32Gb RAM machine ought to work just fine. Building the maps with multiple threads requires some synchronization, but that's done only once. The queries can be read-only: no synchronization required. A nice 10 core machine ought to do a billion queries in well less than a minute.
There is very easy Answer which works
Create Grid of NxN
Now for each Lamp increment the count of all the cells which suppose to be illuminated by the Lamp.
For each query check if cell on that query has value > 0;
For each adjacent cell find out all illuminated cells and reduce the count by 1
This worked fine but failed for size limit when trying for 10000 X 10000 grid
The problem i have goes as follows (simplified):
I have a board, represented as a matrix of n x m squares (n might equal m)
In it, there are p game pieces
Each game piece has a pre-defined speed, which is how many steps it can take in it's turn
Pieces can't overlap
There are three types of cells: those which don't require extra movements to be crossed (you loose 0 extra speed when going through), those which require 1 extra movement to be crossed and some which you simply can't get through (like a wall)
So, given a game piece in a certain [i,j] position in my game board, i want to find out:
a) All the places it can move to, with it's speed
b) The path to a certain [k,l] position in the board
Having a) solved, b) is almost trivial.
Currently the algorithm i'm using goes as follows, assuming a language where arrays of size n go from 0 to n-1:
Create a sqaure matrix of speed*2+1 size which represents the cost of moving as if all cells had no extra cost to be crossed (the piece is on the position [speed, speed])
Create another square matrix of speed*2+1 size which has the extra costs of each cell (those which can't be crossed because either it's a wall or there is another piece in it has a value of infinite)(the piece is on the position [speed, speed])
Create another square matrix of speed*2+1 size which is the sum of the former two(the piece is on the position [speed, speed])
Correct the latter matrix making sure the value of each cell is: the minimal cost of all the adjacent cells + 1 + the extra cost of the cell. If it isn't, i correct it and start with the matrix all over again.
An example:
P are pieces, W are walls, E are empty cells which require no extra movement, X are cells which require 1 extra movement to be crossed.
X,E,X,X,X
X,X,X,X,X
W,E,E,E,W
W,E,X,E,W
E,P,P,P,P
The first matrix:
2,2,2,2,2
2,1,1,1,2
2,1,0,1,2
2,1,1,1,2
2,2,2,2,2
The second matrix:
1,0,1,inf,1
1,1,1,1,1
inf,0,0,0,inf
inf,0,1,0,inf
0,inf,inf,inf,inf
The sum:
3,2,3,3,3
3,2,2,2,3
inf,1,0,1,inf
inf,1,2,1,inf
inf,inf,inf,inf,inf
Since [0,0] is not 2+1+1, i correct it:
The sum:
4,2,3,3,3
3,2,2,2,3
inf,1,0,1,inf
inf,1,2,1,inf
inf,inf,inf,inf,inf
Since [0,1] is not 2+1+0, i correct it:
The sum:
4,3,3,3,3
3,2,2,2,3
inf,1,0,1,inf
inf,1,2,1,inf
inf,inf,inf,inf,inf
Since [0,2] is not 2+1+1, i correct it:
The sum:
4,2,4,3,3
3,2,2,2,3
inf,1,0,1,inf
inf,1,2,1,inf
inf,inf,inf,inf,inf
Which one is the correct answer?
What I want to know is if this problem has a name I can search it by (couldn't find anything) or if anybody can tell me how to solve the point a).
Note that I want the optimal solution, so I went with a dynamic programming algorithm. Might random walkers be better? AFAIK, this solution is not failing (yet), but I have no proof of correctness for it, and I want to be sure it works.
A-star is a standard algorithm to determine shortest path give obstacles on a 2d board and cost per square of moving. You can also use it to test if a specific move is valid, but to actually generate all valid moves I would simply start ay the start position, move in each direction by one square mark which squares are valid and then repeat from each of your new places making sure not to visit the same square again. It will be a recursive algorithm calling itself at most 4 times on each call and will generate you valid moves efficiently. If there are constraints like how many squares you can move at once with different costs just pass the running total of how far you've come for each square.
I have got a 3D grid (voxels), where some of the voxels are filled, and some are not. The 3D grid is sparsely filled, so I have got a set filledVoxels with coordinates (x, y, z) of the filled voxels. What I am trying to do is find out is for each filled voxel, how many neighboring voxels are filled too.
Here is an example:
filledVoxels contains the voxels (1, 1, 1), (1, 2, 1), and (1, 3, 1).
Therefore, the neighbor counts are:
(1,1,1) has 1 neighbor
(1,2,1) has 2 neighbors
(1,3,1) has 1 neighbor.
Right now I have this algorithm:
voxelCount = new Map<Voxel, Integer>();
for (voxel v in filledVoxels)
count = checkAllNeighbors(v, filledVoxels);
voxelCount[v] = count;
end
checkAllNeighbors() looks up all 26 surrounding voxels. So in total I am doing 26*filledVoxels.size() lookups, which is quite slow.
Is there any way to cut down the number of required lookups? When you look at the above example you can see that I am checking the same voxels several times, so it might be possible to get rid of lookups with some clever caching.
If this helps in any way, the voxels represent a voxelized 3D surface (but there might be holes in it). I usually want to get a list of all voxels that have 5 or 6 neighbors.
You can transform your voxel space into a octree in which every node contains a flag that specifies whether it contains filled voxels at all.
When a node does not contain filled voxels, you don't need to check any of its descendants.
I'd say if each of your lookups is slow (O(size)), you should optimize it by binary search in an ordered list (O(log(size))).
The constant 26, I wouldn't worry much. If you iterate smarter, you could cache something and have 26 -> 10 or something, I think, but unless you have profiled the whole application and found out decisively that it is the bottleneck I would concentrate on something else.
As ilya states, there's not much you can do to get around the 26 neighbor look-ups. You have to make your biggest gains in efficiently identifying whether a given neighbor is filled or not. Given that the brute force solution is essentially O(N^2), you have a lot of possible ground to gain in that area. Since you have to iterate over all filled voxels at least once, I would take an approach similar to the following:
voxelCount = new Map<Voxel, Integer>();
visitedVoxels = new EfficientSpatialDataType();
for (voxel v in filledVoxels)
for (voxel n in neighbors(v))
if (visitedVoxels.contains(n))
voxelCount[v]++;
voxelCount[n]++;
end
next
visitedVoxels.add(v);
next
For your efficient spatial data type, a kd-tree, as Zifre suggested, might be a good idea. In any case, you're going to want to reduce your search space by binning visited voxels.
If you're marching along the voxels one at a time, you can keep a lookup table corresponding to the grid, so that after you've checked it once using IsFullVoxel() you put the value in this grid. For each voxel you're marching in you can check if its lookup table value is valid, and only call IsFullVoxel() it it isn't.
OTOH it seems like you can't avoid iterating over all neighboring voxels, either using IsFullVoxel() or the LUT. If you had some more a priori information it could help. For instance, if you knew that there were at most x neighboring filled voxels, or you knew that there were at most y neighboring filled voxels in each direction. For instance, if you know you're looking for voxels with 5 to 6 neighbors, you can stop after you've found 7 full neighbors or 22 empty neighbors.
I'm assuming that a function IsFullVoxel() exists that returns true if a voxel is full.
If most of the moves in your iteration were to neighbors, you could reduce your checking by around 25% by not looking back at the ones you just checked before you made the step.
You may find a Z-order curve a useful concept here. It lets you (with certain provisos) keep a sliding window of data around the point you're currently querying, so that when you move to the next point, you don't have to throw away many of the queries you've already performed.
Um, your question is not very clear. I'm assuming you just have a list of the filled points. In that case, this is going to be very slow, because you have to iterate through it (or use some kind of tree structure such as a kd-tree, but this will still be O(log n)).
If you can (i.e. the grid is not too big), just make a 3d array of bools. 26 lookups in a 3d array shouldn't really take that long (and there really is no way to cut down on the number of lookups).
Actually, now that I think of it, you could make it a 3d array of longs (64 bits). Each 64 bit block would hold 64 (4 x 4 x 4) voxels. When you are checking the neighbors of a voxel in the middle of the block, you could do a single 64 bit read (which would be much faster).
Is there any way to cut down the number of required lookups?
You will, at minimum, have to perform at least 1 lookup per voxel. Since that's the minimum, then any algorithm which only performs one lookup per voxel will meet your requirement.
One simplistic idea is to initialize an array to hold the count for each voxel, then look at each voxel and increment the neighbors of that voxel in the array.
Pseudo C might look something like this:
#define MAXX 100
#define MAXY 100
#define MAXZ 100
int x, y, z
char countArray[MAXX][MAXY][MAXZ];
initializeCountArray(MAXX, MAXY, MAXZ); // Set all array elements to 0
for(x=0; x<MAXX; x++)
for(y=0;y<MAXY;y++)
for(z=0;z<MAXZ;z++)
if(VoxelExists(x,y,z))
incrementNeighbors(x,y,z);
You'll need to write initializeCountArray so it sets all array elements to 0.
More importantly you'll also need to write incrementNeighbors so that it won't increment outside the array. A slight speed increase here is to only perform the above algorithm on all voxels on the interior, then do a separate run on all the outside edge voxels with a modified incrementNeighbrs routine that understands there won't be neighbors on one side.
This algorithm results in 1 lookup per voxel, and at most 26 byte additions per voxel. If your voxel space is sparse then this will result in very few (relative) additions. If your voxel space is very dense, you might consider reversing the algorithm - initialize the array to the value of 26 for each entry, then decrement the neighbors when a voxel doesn't exist.
The results for a given voxel (ie, how many neighbors do I have?) reside in the array. If you need to know how many neighbors voxel 2,3,5 has, just look at the byte in countArray[2][3][5].
The array will consume 1 byte per voxel. You could use less space, and possibly increase the speed a little bit by packing the bytes.
There are better algorithms if you know details about your data. For instance, a very sparse voxel space will benefit greatly from an octree, where you can skip large blocks of lookups when you already know there are no filled voxels inside. Most of these algorithms, however, would still require at least one lookup per voxel to fill their matrix, but if you are performing several operations then they may benefit more than this one operation.