Game - collection of characters and random movement collision - list

I am trying to make a simulation of a rabbit population. these rabbits are printed on a grid say 50x50 on a console app.
I have several questions which would really help.
If I want to keep a record of all the bunnehs with their individual characteristics, is a List the best way to record this data?
For random movement, I generate a random move (-1,0,+1) on the x-axis and on the y-axis.
If i want to avoid collision against other existing rabbits, is calculating the new x,y and comparing them against the list the only way.
like:
foreach(Bunny bunny2 in lst)
if (bunny2.x == newbunny.x && bunny2.y == newbunny.y)
then move newbunny again
Thank you for your time

Based on what you're talking about, I'd use a 2 dimensional to hold all of your bunnies. e.g.
Bunny[49][49] grid; //make a 2D array of bunny objects
This way you can have your data structure perfectly represent your system. Then you could actually use the indices (x, y) of the grid to map to the 2D array. For example this would get you the bunny at x = 3, y = 17:
Bunny myBunny = grid[2][16]
Also this would ease in collision detection, as you can just check if there is a bunny in the relevant grid space you want to move to, so if the bunny in the previous example wanted to go x-1 spaces, then you could check if that grid coordinate had a null value:
if(grid[1][16] == null) { //then bunny can go there
//code to move bunny
grid[2][16] = null //remove bunny from old grid space
} else { //buny can't go there
//code
}
NB! In order for this to work, you need to make sure you take the bunny OUT of the grid space it is moving from, as done in the previous example. That way you maintain where there are no bunnies versus where they are.

Related

Waterfall Rock Hit Counter

I'm having a difficulity in solving a problem from my class, it's about dynamic programming (or so my professor called it). The problem is called Waterfall Rock Hit. (Time limit : 1s, Memory Limit : 16mb)
We're given the upper left (v1, h1) and lower right coordinate (v2, h2) of the rock and we simulate a waterfall and count number of rock hit by the water, imagine the water started falling from a coordinate (x,y), it will fall to (x-1, y) and continue to fall until it hit a rock. when it hit a rock, the water will split to the right and left, and follow the length of the rock, here's the a picture of how the algorithm will work.
Simulation Picture.
What we need to watch here, if the rock was hit more than once, the problem also guaranteed there won't any rock stick to each other, and the water will always find a way through any 2 rocks.
Here's a piece of my incomplete code, where i still thinking of the second condition for when the water hit the rock and preventing double count.
int maks=0, n, m, nstone;
struct a{
int v1, v2, h1, h2; //coordinates
bool pass; //passed or not?
}; a arr[5000];
bool acompare(a lhs, a rhs){
return lhs.v1 < rhs.v1; //compare height descending
}
int fall(int x, int y){
if (x == n || y == m || y == -1) //if the water passed the wall
return 0;
else if () //the confusing condition if the water hit the rock
return 1 + fall(x, h1-1) + fall(x, h2+1));
else // if there's nothing below
return fall(x-1, y);
}
int main(){
cin>> n>> m>> nstone; //waterfall size (n*m) and number of stone
for (int i=0; i<nstone; i++){ //read the stone's corner
cin>> arr[i].v1>> arr[i].h1>> arr[i].v2>> arr[i].h2;
arr[i].pass = false;
}
sort(arr, arr+nstone, acompare); //sort the stone's based on height
cin>> start; //read the start point of the water
cout<< fall(start, m)<< endl;
return 0;
}
testcase sample input :
6 6 3
2 3 2 4
4 2 5 2
5 5 6 5
output :
3
First, the condition you have trouble with. It's inefficient to iterate all rocks on each step, even binary search is not optimal. This can be solved by a table, like in a board game. Create a NxM 2D array for this (e.g. 4 bytes each item = 250000 * 4 bytes = 2MB, far away from your 16MB limit) and mark all points covered by rocks. On each step you'll need to check a single point if it's a rock.
Secondly, it's a DP problem because streams can merge like the one in the bottom middle:
..|..
.|X|.
.|.|.
|X|X|
|.|.|
Your approach would calculate this stream twice. (BTW, I don't see where you use your bool pass; //passed or not? member) Once calculated store the number of rocks the stream has hit in your board game table, e.g. in your example:
.1331.
.1XX1.
010.1.
0X0010
0X00X0
0.00X0
So next time you reach already calculated point of a stream you already know how many rocks you hit from this point.
I see that you don't use std::vector and use C-style array instead. I would assume that you're not familiar with C++ STL library and hence will provide an answer that uses as little of C++ STL as possible.
Because there are multiple stones to check, you need to use a loop (or std::find_if) to check all of them.
for(int stone_index=0;stone_index<nstone;++stone_index)
For each stone, check if the (x,y) coordinate is right on the top of that stone.
Once you've found one, it's guaranteed that you won't found any other ones (because stones don't touch), so just return immediately.
return 1 + fall(x, h1-1) + fall(x, h2+1));
(this is just pseudocode, replace h1 and h2 with suitable values)
If you reach the end of the loop without finding a stone,
// if there's nothing below
return fall(x-1, y);
Note that this solution requires nstone steps to check, you can do better using a std::map or something. That may be too hard for you.

C++: Remove repeated numbers in a matrix

I want to remove numbers from a matrix that represents coordinates with the format 'x y z'. One example:
1.211 1.647 1.041
2.144 2.684 1.548
1.657 2.245 1.021
1.657 0.984 2.347
2.154 0.347 2.472
1.211 1.647 1.041
In this example the coordinates 1 and 6 are the same (x, y and z are the same) and I want to remove them but I do not want to remove cases with only one value equal as coordinates 3 and 4 for x-coordinate).
These values are in a text file and I want to print the coordinates without duplication in another file or even in the same one.
A very simple solution would be to treat each line as a string and use a set of strings. As you traverse the file line-wise, you check if the current line exists in the set and if not, you insert and print it.
Complexity: O(nlogn), extra memory needed: almost the same as your input file in the worst case
With the same complexity and exactly the worst case memory consumption as the previous solution, you can load the file in memory, sort it line-wise, and then easily skip duplicates while printing. The same can be done inside the file if you are allowed to re-order it, and this way you need very little extra memory, but be much slower.
If memory and storage is an issue (I'm assuming since you can't duplicate the file), you can use the simple method of comparing the current line with all previous lines before printing, with O(n^2) complexity but no extra memory. This however is a rather bad solution, since you have to read multiple times from the file, which can be really slow compared to the main memory.
How to do this if you want to preserve the order.
Read the coordinates into an array of structures like this
struct Coord
{
double x,y,z;
int pos;
bool deleted;
};
pos is the line number, deleted is set to false.
Sort the structs by whatever axis tends to show the greatest variation.
Run through the array comparing the value of the axis you were using in the sort from the previous item to the value in the current item. If the difference is less than a certain preset delta (.i.e. if you care about three digits after the decimal point you would look for a difference of 0.000999999 or so) you compare the remaining values and set deleted for any line where x,y,z are close enough.
for(int i=1;i<count;i++)
{
if(fabs(arr[i].x-arr[i-1].x)<0.001)
if(fabs(arr[i].y-arr[i-1].y)<0.001)
if(fabs(arr[i].z-arr[i-1].z)<0.001)
arr[i].deleted=true;
}
sort the array again, this time ascending by pos to restore the order.
Go through the array and output all items where deleted is false.
In c++, you can use the the power of STL to solve this problem. Use the map and store the three coordinates x, y and z as a key in the map. The mapped value to the key will store the count of that key.
Key_type = pair<pair<float,float>,float>
mapped_type = int
Create a map m with the above given key_type and mapped_type and insert all the rows into the map updating the count for each row. Let's assume n is the total number of rows.
for(i = 0; i < n; i++) {
m[make_pair(make_pair(x,y),z)]++;
}
Each insertion takes O(logn) and you have to insert n times. So,overall time complexity will be O(nlogn). Now, loop over all the rows of the matrix again and if the mapped_value of that row is 1, then it is unique.

Efficient data structure for sparse data lookup

Situation:
Given some points with coordinate (x, y)
Range 0 < x < 100,000,000 and 0 < y <100,000,000
I have to find smallest square which contains at least N no of points on its edge and inside it.
I used vector to store coordinates and searched all squares with side length minLength upto side length maxLength (Appling Brute Force in relevant space)
struct Point
{
int x;
int y;
};
vector<Point> P;
int minLength = sqrt(N) - 1;
int maxLength = 0;
// bigx= largest x coordinate of any point
// bigy= largest y coordinate of any point
// smallx= smallest x coordinate of any point
// smally= smallest y coordinate of any point
(bigx - smallx) < (bigy - smally) ? maxLength = (bigx - smallx) : maxLength = (bigy - smally);
For each square I looked up, traversed through complete vector to see if at least N points are on its edge and inside it.
This was quite time inefficient.
Q1. What data structure should I use to improve time efficiency without changing Algorithm I used?
Q2. Efficient Algorithm for this problem?
There are points on 2 opposite edges - if not, you could shrink the square by 1 and still contain the same number of points. That means the possible coordinates of the edges are limited to those of the input points. The input points are probably not on the corners, though. (For a minimum rectangle, there would be points on all 4 edges as you can shrink one dimension without altering the other)
The next thing to realize is that each point divides the plane in 4 quadrants, and each quadrant contains a number of points. (These can add up to more than the total number of points as the quadrants have one pixel overlap). Lets say that NW(p) is the number of points to the northwest of point p, i.e. those that have x>=px and y>=py. Then the number of points in a square is NW(bottomleft) + NW(topright) - NW(bottomright) - NW(topleft).
It's fairly easy to calculate NW(p) for all input points. Sort them by x and for equal x by y. The most northwestern point has NW(p)==0. The next point can have NW(p)==1 if it's to the southeast of the first point, else it has NW(p)==0. It's also useful to keep track of SW(p) in this stage, as you're working through the points from west to east and they're therefore not sorted north to south. Having calculated NW(p), you can determine the number of points in a square S in O(1)
Recall that the square size is restricted by by the need to have points on opposite edges. Assume the points are on the left (western) and right edge - you still have the points sorted by x order. Start by assuming the left edge is at your leftmost x coordinate, and see what the right edge must be to contain N points. Now shift the left edge to the next x coordinate and find a new right edge (and thus a new square). Do this until the right edge of the square is the rightmost point.
Its also possible that the square is constrained in y direction. Just sort the points in y direction and repeat, then choose the smallest square between the two outcomes.
Since you're running linearly through the points in x and y direction, that part is just O(N) and the dominant factor is the O(N log N) sort.
Look at http://en.wikipedia.org/wiki/Space_partitioning for algorithms that use the Divide-and-Conquer technique to solve this. This is definitely solvable in Polynomial time.
Another variant algorithms can be on the following lines.
Generate a vornoi-diagram on the points to get neighbour information. [ O(nlog(n)) ]
Now use Dynamic Programming, the DP will be similar to the problem of finding the maximum subarray in a 2D array. Here instead of the sum of numbers, you will keep count of points before it.
2.a Essentially a recursion similar to this will hold. [ O(n) ]
Number of elements in square from (0,0) to (x,y ) = (Number of elems
from square (0,0 to ((x-1),y))+ (Number of elems in square 0,0 - ( x, y-1))
- (Number of elems in (0,0)-((x-1),(y-1)))
Your recurrence will have to change for all the points on its neighbourhood and to the left and above, instead of just the points above and left as above.
Once the DP is ready, you can query the points in a sqare in O(1).
Another O(n^2) loop to find from all possible combinations and find the least square.
You can even greedily start from the smallest squares first, that way you can end your search as soon as you find a suitable square..
The rtree allows spatial searching, but doesn't have stl implementation, although sqlite would allow binding. This can answer "get all points within range", "k nearest neighbours"
Finding a region which has the most dense data, is a problem similar to clustering.
Iterating over the points and finding the N nearest entries to each point. Then generate the smallest circle - centre would be the Max(x) - min(x), Max(y) - min(y). A square can be formed which contains all the neighbours, and would be somewhere between 2r length and 2sqrt(r) length sides compared to circle.
Time taken O(x) to build structure
O(X N log(X)) to search for smallest cluster
Note: There are a bunch of answers for your second question (which will probably reap bigger benefits), but I'm only referring to your first one, i.e. what data to use without changing the algorithm.
There, I think that your choice using a vector is already pretty good, because in general vectors offer the best payload/overhead ratio and also the fastest iteration. In order to find out specific bottlenecks, use a profiler, otherwise you are only guessing. With large vectors, there are a few things to avoid though:
Overallocation, this wastes space.
Underallocation, this causes copying when the vector is grown to the necessary size.
Copying.

Generation of vector Grid For a Game

I am working on a c++ project and I'm stuck. I am trying to generate a grid from a vector that holds what elements are in the grid. Originally, the vector will hold something like(3,3) and I would simply create a grid that looks like this XXX. If it were (3,2,1), it would be XX|X. The first number in the parenthesis represents the total number of X's that is in my Grid(even after an X has been removed) and the consequent number represents the number of X's for each column like shown above.
The problem I'm having is creating a grid that also keeps track of the removed X's so when I want to recreate it, the space for the removed X's is there and not overwritten.
For instance: Initial Grid = XXX|XX =>(5,3,2)
Later Grid = OOX|XX => (3,1,2)
Generating a grid from the "Initial Grid" is simple but generating later grids are hard(for me). For instance, My new vector would hold (3,1,2) for the "Later Grid". If I want to generate the "Later Grid" using the (3,1,2) representation, how should I do it. Any help is greatly appreciated.
This is not a homework, this is a side project that I'm working on.
Would a two-dimensional array not suffice for your program? Say you declare a two-dimensional array of your max map size, then use two independent variables to represent the max grid size there after?
char Map[15][15] = {//...}
int Width = 15;
int Height = 15;
//Map decreases in size...
Width--;
Height--;
//all calculations are now based off of width and height(not the initial size of the array)
if(xpos < Width)
//do stuff
sounds like you're working on a persistence problem. I may not fully understand what you are trying to do, but it sounds like you will be reading a series of tuples in the form (x:int, y:int, z:int)
where
x = total number of 'X'
y = 'X' before vertical bar
z = 'X' after vertical bar
then you want to pad missing 'X' with 'O'.
The problem it seems is that you are loosing information about the initial state of your grid and therefore don't know how many 'O' to pad with.
if I were you I would just add another value to keep track of the initial state. This value would never change and would be populated with the initial number of 'X' when the grid is first generated.
so in your example you have:
Initial Grid = XXX|XX =>(5,3,2) Later Grid = OOX|XX => (3,1,2)
instead try adding an initial state value to the tuple like this
Initial Grid = XXX|XX =>(5,3,2,5) Later Grid = OOX|XX => (3,1,2,5)
now you have a tuple in the form (x:int, y:int, z:int, n:int) where
x = total number of 'X'
y = 'X' before vertical bar
z = 'X' after vertical bar
n = 'X' in initial state
now we can determine the number of 'O' to pad with by evaluating
n - x = number of 'O' to pad with
assuming that the initial number of 'X' varies from tuple to tuple you would need to keep track of the initial 'X' state as well. keeping track the initial number of 'X' will allow you to always discern how many 'O' you need to pad with for every successive iteration of the grid

Algorithms for 3D Mazes [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
Are there algorithms to produce 3 dimensional mazes? Essentially the same as a 2D maze but the Z depth axis can be traversed? The idea is still the same though, to get from Start to End. Could backtracking still be used?
Which algorithm should I use to generate a 3D maze?
See here. I mean that you can go into the cube too, not just iterate the faces of it.
I made 2d mazes a few years ago using Kruskal's Algorithm here. There should be no reason this couldn't work with the 3d case you described. Basically you'd consider a cell a cube, and have a large array that has (for every cells), 6 walls in the +/- x, y, and z directions. The algorithm initially starts with all walls everywhere and randomly makes walls disappear until every cell in the maze is connected.
I have the code for generating a 2D maze in, of all things, RPGLE (something I did as a self-exercise while learning the language). Because of the way I wrote it, about the only changes necessary for the general alogrithm would be to add the Z dimension as an additional dimension...
The entire thing is 20 pages long (although this includes input/output), so here's some code. You should be able to translate this into whatever language you need: I translated it from spaghetti-code BASIC (gotos were way overused here, yeah. But it was a fun exercise).
//set out maximum maze size
maximumMazeSquareCounter = mazeHorizontalSize * mazeVerticalSize + 1;
// generate a starting horizontal positiongetRandomNumber(seed : randomNumber);
currentHorizontalPosition = %inth(randomNumber * (mazeHorizontalSize - 1)) + 1;
currentVerticalPosition = 1;
mazeSquareCounter = 1;
// generate the top row of the maze (with entrance)
mazeTopRow = generateEntrance(currentHorizontalPosition);
//write to the printer file
writeMazeDataLine(mazeTopRow);
mazeSquareCounter += 1;
//set the first position in the maze(the entry square
setPathPoint(currentHorizontalPosition : currentVerticalPosition);
//do until we've reached every square in the maze
dou mazeSquareCounter >= maximumMazeSquareCounter;
//get the next available random direction
mazeDirection = getNextRandomDirection(getNextAvailableDirection(currentHorizontalPosition : currentVerticalPosition));
//select what to do by the returned results
select;
//when FALSE is returned - when the maze is trapped
when mazeDirection = FALSE;
//if not at the horizontal end of the maze
if currentHorizontalPosition <> mazeHorizontalSize;
//add one to the position
currentHorizontalPosition += 1;
//else if not at the vertical end of the maze
elseif currentVerticalPosition <> mazeVerticalSize;
//reset the horizontal position
currentHorizontalPosition = 1;
//increment the vertical position
currentVerticalPosition += 1;
//otherwise
else;
//reset both positions
currentHorizontalPosition = 1;
currentVerticalPosition = 1;
endif;
//when 'N' is returned - going up (other directions removed)
when mazeDirection = GOING_NORTH;
//set the point above current as visited
setPathPoint(currentHorizontalPosition : currentVerticalPosition - 1);
//set the wall point to allow passage
setWallDirection(currentHorizontalPosition : currentVerticalPosition : GOING_NORTH);
//change the position variable to reflect change
currentVerticalPosition -= 1;
//increment square counter
mazeSquareCounter += 1;
endsl;
enddo;
//generate a random exit
// get a random number
getRandomNumber(seed : randomNumber);
// set to the horzontal position
currentHorizontalPosition = %inth(randomNumber * (mazeHorizontalSize - 1)) + 1;
//set the vertical position
currentVerticalPosition = mazeVerticalSize;
//set wall to allow for exit
setWallDirection(currentHorizontalPosition : currentVerticalPosition : GOING_SOUTH);
The entire thing is backed by two two-dimensional arrays (well, the RPG equivalent): One for the walls that occupy the 'square', and the other for whether or not that square has been visited. The maze is created after every square has been visited. Garuanteed one-path only, worm-turns maze.
To make this three-dimensional, make it use three-dimensional arrays, and add the necessary dimension index.
I designed an algorithm some time ago for 2D mazes on a square grid, there is no reason why this shouldn't also work for a 3D maze on a cubic grid.
Start with a 3D grid initially fully populated with wall cells.
...
Start an agent at an edge of the grid, the agent travels in a straight line in the X, Y, Z, -X, -Y or -Z direction clearing wall as she travels.
Action 'N' has a small chance of occurring each step.
Action 'M' occurs when the cell directly in front of the agent is wall and the cell in front of that is empty.
'N' is a random choice of:
removing that agent
turning left or right 90 degrees
and creating an agent on the same square turned 90 degrees left, right or both (two agents).
'M' is a random choice of:
removing that agent
removing the wall in front of that agent and then removing that agent
and doing nothing, carrying on
turning left or right 90 degrees.
and creating an agent on the same square turned 90 degrees left, right or both (two agents).
The mazes are distinctive, and their character is highly flexible by adjusting the trigger for 'M' (to do with valid junctions) and by also adjusting the chances of 1 to 8 occurring. You may want to remove an action or two, or introduce your own actions, for example one to make a small clearing or sidestep one step.
The trigger for 'N' can also be another sort of randomness, for example the example below can be used to create fairly branchy mazes that still have some long straight parts.
float n = 1;
while (random_0_to_1 > 0.15)
{
n *= 1.2;
}
return (int)n;
Some small adjustments will be needed from my simple description, for example trigger for action 'M' will need to check the cells adjacent to the cells it checks as well depending on what sort of junctions are desirable.
Either 5 or 6 are needed for the maze to contain cycles and at least one alternative 'M' action to 5 and 6 is required for the maze to contain dead ends.
Some choices of chances/actions and 'M' triggers will tend to make mazes that don't work, for example are unsolvable or full of empty or wall cells, but many will produce consistently nice results.