so I have this class:
class Piece{
int width;
int height;
}
my problem is that I need to make a container type class that somehow can save the layout of multiple and different size "Piece" objects (note that Piece can only represent rectangles).
Example:
________
| t |
| t jj |
| t jj |
_________
My goal with this is to be able to "fill" a empty rectangle with multiple "Piece" objects but with the ability to know if the "Piece" can fit in.
I'm developing this in C++. I started with the most logic solution I think that was to use a "matrix" of vectors (vector< vector< Piece * > > mat) but that doesn't work because as I said "Piece" objects can have different sizes.
I hope you can give some hints on how to get a solution for this or if it exists some lib or open-sorce project links.
Thank you.
EDIT
I forgot this:I know beforehand the dimensions of the container and the insertion (after validation) is sequential (Piece after Piece) with no predefined orientation.
You can use Piece p[width][height] and use memset to make all zeros or use a std::vector if you don't know the size of the grid beforehand. Then you can check(while adding a new Piece at some position (x, y)) if on any of its subsquares there is some other Piece already.
Edit: You can use a matrix char mem[sqrt(width)][sqrt(height)]; and a one vector of Pieces. Then using the matrix if there will be a probable collision and if not, just add the Piece. Else you iterate through all the existing ones and check for a collision.
If you want to make the procedure faster( this one is reasonable only with small grids ), then you will need to use more "advanced" data structures. What I suggest you is to learn about 2D BIT(or fenwick) trees(there are a lot of resources on google). You can also use 2D segment trees. Then when adding a new Piece at position (x, y) check the sum of all squares in it(e.g from (x, y) to (x + width, y + height)). If that sum is zero then the new Piece won't collide with previous ones and you then update the grid as you add 1 to all squares in your Piece(I mean to the corresponding values in the 2D segment tree). Else if the sum is greater than zero it means that there will be some overlap and you must then discard the new Piece.
Related
I am working on a project that has a small component requiring the comparison of distributions over image gradients. Assume I have computed the image gradients in the x and y directions using a Sobel filter and have for each pixel a 2-vector. Obviously getting the magnitude and direction is reasonably trivial and is as follows:
However, what is not clear to me is how to bin these two components in to a two dimensional histogram for an arbitrary number of bins.
I had considered something along these lines(written in browser):
//Assuming normalised magnitudes.
//Histogram dimensions are bins * bins.
int getHistIdx(float mag, float dir, int bins) {
const int magInt = reinterpret_cast<int>(mag);
const int dirInt = reinterpret_cast<int>(dir);
const int magMod = reinterpret_cast<int>(static_cast<float>(1.0));
const int dirMod = reinterpret_cast<int>(static_cast<float>(TWO_PI));
const int idxMag = (magInt % magMod) & bins
const int idxDir = (dirInt % dirMod) & bins;
return idxMag * bins + idxDir;
}
However, I suspect that the mod operation will introduce a lot of incorrect overlap, i.e. completely different gradients getting placed in to the same bin.
Any insight in to this problem would be very much appreciated.
I would like to avoid using any off the shelf libraries as I want to keep this project as dependency light as possible. Also I intend to implement this in CUDA.
This is more of a what is an histogram question? rather than one of your tags. Two things:
In a 2D plain two directions equal by modulation of 2pi are in fact the same - so it makes sense to modulate.
I see no practical or logical reason of modulating the norms.
Next, you say you want a "two dimensional histogram", but return a single number. A 2D histogram, and what would make sense in your context, is a 3D plot - the plane is theta/R, 2 indexed, while the 3D axis is the "count".
So first suggestion, return
return Pair<int,int>(idxMag,idxDir);
Then you can make a 2D histogram, or 2 2D histograms.
Regarding the "number of bins"
this is use case dependent. You need to define the number of bins you want (maybe different for theta and R). Maybe just some constant 10 bins? Maybe it should depend on the amount of vectors? In any case, you need a function that receives either the number of vectors, or the total set of vectors, and returns the number of bins for each axis. This could be a constant (10 bins) initially, and you can play with it. Once you decide on the number of bins:
Determine the bins
For a bounded case such as 0<theta<2 pi, this is easy. Divide the interval equally into the number of bins, assuming a flat distribution. Your modulation actually handles this well - if you would have actually modulated by 2*pi, which you didn't. You would still need to determine the bin bounds though.
For R this gets trickier, as this is unbounded. Two options here, but both rely on the same tactic - choose a maximal bin. Either arbitrarily (Say R=10), so any vector longer than that is placed in the "longer than max" bin. The rest is divided equally (for example, though you could choose other distributions). Another option is for the longest vector to determine the edge of the maximal bin.
Getting the index
Once you have the bins, you need to search the magnitude/direction of the current vector in your bins. If bins are pairs representing min/max of bin (and maybe an index), say in a linked list, then it would be something like (for mag for example):
bin = histogram.first;
while ( mag > bin.min ) bin = bin.next;
magIdx = bin.index;
If the bin does not hold the index you can just use a counter and increase it in the while. Also, for the magnitude the final bin should hold "infinity" or some large number as a limit. Note this has nothing to do with modulation, though that would work for your direction - as you have coded. I don't see how this makes sense for the norm.
Bottom line though, you have to think a bit about what you want. In any case all the "objects" here are trivial enough to write yourself, or even use small arrays.
I think you should arrange your bins in a square array, and then bin by vx and vy independently.
If your gradients are reasonably even you just need to scan the data first to accumulate the min and max in x and y, and then split the gradients evenly.
If the gradients are very unevenly distributed, you might want to sort the (eg) vx first and arrange that the boundaries between each bin exactly evenly divides the values.
An intermediate solution might be to obtain the min and max ignoring the (eg) 10% most extreme values.
I'm creating a game in Qt in c++, and I store every coordinate of specific size into a vector like :
std::vector<std::unique_ptr<Tile>> all_tiles = createWorld(bgTile);
for(auto & tile : all_tiles) {
tiles.push_back(std::move(tile));
}
Each level also has some healthpacks which are stored in a vector aswell.
std::vector<std::unique_ptr<Enemy>> all_enemies = getEnemies(nrOfEnemies);
for(auto &healthPackUniquePtr : all_healthpacks) {
std::shared_ptr<Tile> healthPackPtr{std::move(healthPackUniquePtr)};
int x = healthPackPtr->getXPos();
int y = healthPackPtr->getYPos();
int newYpos=checkOverlapPos(healthPackPtr->getXPos(),healthPackPtr->getYPos());
newYpos = checkOverlapEnemy(healthPackPtr->getXPos(),newYpos);
auto healthPack = std::make_shared<HealthPack>(healthPackPtr->getXPos(), newYpos, healthPackPtr->getValue());
healthPacks.push_back(healthPack);
}
But know I'm searching for the fastest way to check if my player position is at an healthpack position. So I have to search on 2 values in a vector : x and y position. Anyone a suggestion how to do this?
Your 'real' question:
I have to search on 2 values in a vector : x and y position. Anyone a
suggestion how to do this?"
Is a classic XY question, so I'm ignoring it!
I'm searching for the fastest way to check if my player position is at
an healthpack position.
Now we're talking. The approach you are using now won't scale well as the number of items increase, and you'll need to do something similar for every pair of objects you are interested in. Not good.
Thankfully this problem has been solved (and improved upon) for decades, you need to use a spacial partitioning scheme such as BSP, BVH, quadtree/octree, etc. The beauty of the these schemes is that a single data structure can hold the entire world in it, making arbitrary item intersection queries trivial (and fast).
You can implement a callback system. Then a player moves a tile, fire a callback to that tile which the player is on. Tiles should know its state and could add health to a player or do nothing if there is nothing on that tile. Using this technique, you don`t need searching at all.
If all_leathpacks has less than ~50 elements I wouldn't bother to improve. Simple loop is going to be sufficiently fast.
Otherwise you can split the vector into sectors and check only for the elements in the same sector as your player (and maybe a few around if it's close to the edge).
If you need something that's better for the memory you and use a KD-tree to index the healtpacks and search for them fast (O(logN) time).
Ok so I have a 2d vector of chars that I call a grid. Lets just say its 70 x 30. When the grid is created, it automatically fills each position with 'x'
I have a function that displays the grid. So I call this function and a 70x30 grid of x's is displayed to the console.
I have another function that I want to call to essentially replace the char at certain x,y coordinates of the grid with a different char. The points aren't exactly random/scattered. I'm basically starting from a point on the edge of the grid, and drawing zigzagged lines to another edge. All points are predetermined. Theres a lot of points to plot, so manually doing it seems inefficient.
Here's how I was thinking to do it:
Create a double for loop, width and height, calling them i and j
If i = (a || b || c || d...) && j = (e || f || g..)
And essentially do that tedious process for each possible scenario..
Surely there is a much easier and simpler way lol. Any suggestions will be greatly appreciated. Thanks!
If the points can be pre-determined by having a map (as in for a level editor or otherwised fixed pattern), then make a dictionary of x/y co-ordinates to what the tile becomes. Iterate over the dictionary and do each replacement.
If the points aren't pre-determined but follow a pattern, such as lines or blobs, then write a method that draws the line/blob/whatever and call it over and over. The method decides which tiles to replace and replaces those.
Btw, there's a trick when doing 2D checking and processing like this which is called having a 'delta', for instance xdelta=-1, ydelta=0 is west and xdelta=1, ydelta=1 is northeast. By having a delta you can run a function two, four or eight times with different deltas and it'll move in different directions by just using the delta's directions instead of needing to try all eight directions on its own - the delta can also be used to drive the bounds checking if you want, as you can't go out of bounds in a direction you're not proceeding in for example. Then you can go further and have an enumeration of all directions, functions that invert a direction, that turn a direction 90/45 degrees (if it's enumerated it's very simple, you just add 2 or 1 to the enumeration and return the new direction), etc, making processing very easy now.
So I might have something like
function drawLine(int xstart, int ystart, int xdelta, intydelta)
that starts at xstart,ystart, replaces the tile with O, adds xdelta to x, adds ydelta to y, replaces the tile with O, etc until it falls off the edge.
I'm writing a program that is supposed
to sort a number of square tiles (of which
each side is colored in one of five colors—red, orange,
blue, green and yellow), that are laying next to each other
(eg 8 rows and 12 columns) in a way that as many sides with
the same color connect as possible.
So, for instance, a tile with right side colored
red should have a tile on the right that has a red left-side.)
The result is evaluated by counting how many non-matching pairs
of sides exist on the board. I'm pretty much done with the actual program;
I just have some trouble with my sorting algorithm. Right now I'm using
Bubble-sort based algorithm, that compares every piece on the board
with every other piece, and if switching those two reduces the amount of
non-matching pairs of sides on the board, it switches them. Here a
abstracted version of the sorting function, as it is now:
for(int i = 0 ; i < DimensionOfBoard.cx * DimensionOfBoard.cy ; i++)
for(int j = 0 ; j < DimensionOfBoard.cx * DiemsionOfBoard.cy ; j++)
{
// Comparing a piece with itself is useless
if(i == j)
continue;
// v1 is the amount of the nonmatching sides of both pieces
// (max is 8, since we have 2 pieces with 4 sides each (duh))
int v1 = Board[i].GetNonmatchingSides() + Board[j].GetNonmatchingSides();
// Switching the pieces, if this decreases the value of the board
// (increases the amount of nonmatching sides) we'll switch back)
SwitchPieces(Board[i], Board[j]);
// If switching worsened the situation ...
if(v1 < Board[i].GetNonmathcingSides() + Board[j].GetNonmatchingSides())
// ... we switch back to the initial state
SwitchPieces(Board[i], Board[j]);
}
As an explanation: Board is a pointer to an array of Piece Object. Each Piece has
four Piece-pointers that point to the four adjacent pieces (or NULL, if the Piece is
a side/corner piece.) And switching actually doesn't switch the pieces itself, but
rather switches the colors. (Instead of exchanging the pieces it scrapes off the color
of both and switches that.)
This algorithm doesn't work too bad, it significantly improves the value of the
board, but it doesn't optimize it as it should. I assume it's because side and corner
pieces can't have move than three/two wrong adjacent pieces, since one/two side(s)
are empty. I tried to compensate for that (by multiplying Board[i].GetMatchingPieces()
with Board[i].GetHowManyNonemptySides() before comparing), but that didn't help a bit.
And that's where I need help. I don't know very many sorting algorithms, let alone
those that work with two-dimensional arrays. So can anyone of you know about
an algorithmic concept that might help me to improve my work? Or can anyone see a
problem that I haven't found yet? Any help is appreciated. Thank you.
if there was a switch you have to re-evaluate a board, because there might be previous positions where now you could find an enhancement.
Note that you are going to find only a local minimum with those swappings. You might won't be able to find any enhancements but that doesn't mean that's the best board configuration.
One way to find a better configuration is to shuffle a board and search for a new local minumum, or use an algorithm-skeleten that allows you to make bigger jumps in the state, eg: Simulated annealing.
I'm trying to create a randomized maze in C++, but I can't start because I don't know how to create grids or cells. How could I create it? And I also want to create it using ASCII characters. how can i store it in array? (can any one give a sample code and some explanation so i can understand it better)
Another question: What data stuctures should I need to learn and use? I'm planning to use Eller's algorithm or Kruskal's algorithm.
Thank you guys for helping me! im a begginer programmer, and i want to learn about this, because this is a part of my project, thank you vary much!
Are you looking for Maze generation algorithms (more)? Is your problem with the algorithms, or graphics?
The typical algorithms work by considering each "cell" in the maze as a vertex of a graph, start with all "walls", and remove a set of walls that corresponds to a spanning tree. (So in order to randomize it, many of them start with random weights and find the minimum spanning tree.) For small mazes at least, you don't need any special data structure to represent the cells; you can just think of each cell as a pair (x,y) (its coördinates). And you don't need any data structure (adjacency matrix / adjacency list) to store the edges of the graph either, because the neighbours of (x,y) are just (x,y±1) and (x±1,y) (ignoring those that fall outside the boundaries).
In any case, once you have the spanning tree, you know exactly which of the walls "exist" and which do not, so you have a complete description of the maze. If you're going to draw the maze, you know which ones to draw.
To draw with ASCII characters, you just pass through each row one by one: draw the "upper walls" (put a "--" if the wall between (x,y) and (x,y+1) exists), then draw the actual row (put a "|" if the wall between (x,y) and (x+1,y) exists). Finally draw the bottom boundary.
You probably want to store your maze in a 2-dimension char array. You can declare an array with or without initializing it in C++.
char a[30][10]; // declares a char array of 30 rows and 10 columns.
// declare an array with 3 rows and 3 columns, and provide initial values
char ticTacToeBoard[3][3] = {{'x', 'x', 'o'},
{'o', 'o', 'x'},
{'x', 'o', ' '}
};
You could change the initial values to '|' and '-' for walls in your maze, and use a space character, ' ', for the passageways.
Either initialization method works, but you always use the elements the same way. Here's how you clear the board in the initialized array above.
// clear the board
for (int row=0; row<3; row++) {
for (int col=0; col<3; col++) {
ticTacToeBoard[row][col] = ' ';
}
}
If you want to read the value of an element (useful when you're trying to navigate a maze), you use the same subscript notation as when you're setting its value.
char y = a[2][2]; // reads the character in row 2, column 2
Vertical Wall: |
Horiz. Wall: _
If you're using fixed-width fonts:
_____
| | _
|_ | |
__ | |
|_____|
I'm not sure exactly what to do, but here's where I'd start.
Determine where on your grid the start and end points will be. Then, create a single path, with whatever squiggles you want. Basically, it should be random movement, checking each time that there is still a way for this path to reach the end. Then, remove a certain amount of walls from this path, and create other paths from these holes. Continue this until you run out of empty space. Then, perhaps, ensure that no shorter paths have been created. If they have, block those up.