I'm trying to create a C++ function which controls if N rectangles are collisioning. The N rectangles are in a std::vector. The idea is to compare every element of the vector with others (only one time) to verify if there are collisions.
I already implemented code to do this, but I am looking for a better, cleaner and more elegant way (I'm a C++ newbie).
My code is:
bool areCollisioningNRectangles(std::vector<Rectangle> rect) {
const unsigned long size = rect.size();
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
if (areCollisioningTwoRectangles(rect[i], rect[j])) {
return true;
}
}
}
return false;
}
Related
I am having an issue trying to determine if my arrays contain any duplicate integers. For my Lo Shu Magic Square project, we are to create three different 1-dimensional arrays along with different functions to determine if the input is magic square numbers. I was able to make all other functions work but I cant seem to figure out how to check if the combined array inputs are all unique. Can anyone help? Here is my source code for bool checkUnique.
bool checkUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int TOTAL_NUM)
{
int combinedArray[] = { arrayRow1[0], arrayRow1[1], arrayRow1[2],
arrayRow2[0], arrayRow2[1], arrayRow3[2],
arrayRow3[0], arrayRow3[1], arrayRow3[2] };
for (int counter = 0; counter < TOTAL_NUM; counter++)
{
for (int j = counter; j < TOTAL_NUM; j++)
{
if (j != counter) {
if (combinedArray[counter] == combinedArray[j])
{
return true;
}
}
return false;
}
}
}
I added all elements(TOTAL_NUM = 9) from three different arrays into a new array called combinedArray. When I ran my code and entered 1 2 3 4 5 6 7 8 9, result is still showing that there are duplicates. I tried different methods I found online but still cant get this function to work. Any help would be greatly appreciated
You're quite close to a correct solution, which might look like this:
bool checkUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int TOTAL_NUM)
{
int combinedArray[] = { arrayRow1[0], arrayRow1[1], arrayRow1[2],
arrayRow2[0], arrayRow2[1], arrayRow3[2],
arrayRow3[0], arrayRow3[1], arrayRow3[2] };
for (int counter = 0; counter < TOTAL_NUM; counter++)
{
for (int j = counter; j < TOTAL_NUM; j++)
{
if (j != counter) {
if (combinedArray[counter] == combinedArray[j])
{
return true;
}
}
}
}
return false;
}
The only change relative to your code is that I moved return false; behind the loops. Why? Because you need to check all pairs before you can assert that there are no duplicates.
This solution might be further improved by changing the starting index of the inner loop:
bool checkUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int TOTAL_NUM)
{
int combinedArray[] = { arrayRow1[0], arrayRow1[1], arrayRow1[2],
arrayRow2[0], arrayRow2[1], arrayRow3[2],
arrayRow3[0], arrayRow3[1], arrayRow3[2] };
for (int counter = 0; counter < TOTAL_NUM; counter++)
{
for (int j = counter + 1; j < TOTAL_NUM; j++)
{
if (combinedArray[counter] == combinedArray[j])
return true;
}
}
return false;
}
Here I changed the initializer of the inner loop into int j = counter + 1 so that I'm sure that j will never be equal to counter.
In this solution you need to make up to 36 comparisons. Alternative approaches:
sort combinedArray and check via std::unique whether it contains duplicates.
insert the elements into std::set and check if its size is 9
Since your array is small, these more universal solutions may be not optimal, you'd need to make tests.
Finally a side remark: try to use consistent names to your variables. counter looks very different from j, which suggests that there's a fundamental difference between the two loop control variables. But there's none: they're very similar to each other. So give them similar names. In the same spirit, please use more useful function names. For example, I'd prefer allUnique that would return true if and only if all input umbers are unique. Compare if (checkUnique(a, b, c, 9)) with if (allUnique(a, b, c, 9)). Of course this, in fact, should be called if allUnique(a, b, c, 3), because the information about array lengths is more fundamental than about the effective buffer length.
EDIT
Actually, you have not defined precisely what the expected output of your function is. If you assume that checkUnique should return true if all numbers are different, then rename it to something more significant and swap all true and false:
bool allUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int TOTAL_NUM)
{
int combinedArray[] = { arrayRow1[0], arrayRow1[1], arrayRow1[2],
arrayRow2[0], arrayRow2[1], arrayRow3[2],
arrayRow3[0], arrayRow3[1], arrayRow3[2] };
for (int counter = 0; counter < TOTAL_NUM; counter++)
{
for (int j = counter + 1; j < TOTAL_NUM; j++)
{
if (combinedArray[counter] == combinedArray[j])
return false;
}
}
return true;
}
I've tried many methods and this one is one of them:
void init_table(int _table[][MAX_COLUMNS]) {
for (int i = 0; i < MAX_COLUMNS; i++) {
for (int j = 0; j < MAX_ROWS; j++) {
_table[i][j] = -1;
}
}
}
I am just trying to figure out how to initialize my array with -1 rather than 0 it defaults to.
If you need to fill by the same value, use std::fill:
std::fill(_table, _table + MAX_ROWS*MAX_COLUMNS, -1);
Of course, if you use padding or other advanced techniques, you should take this into account and adjust your code, but this is more advanced topics and should be considered separately.
I've got a tree structure and a running example of how to iterate over it but as I'm a beginner when it comes to performance in coding, I wanted to ask if somebody knows a way to make it faster.
Eigen3 is used to build vectors.
The struct:
struct linkedBoxes{
std::vector<Vector3r> points;
std::vector<linkedBoxes*> boxes;
int sideLength;
};
And the algorithm:
std::vector<Vector3r> integPoints;
std::vector<linkedBoxes*> stack;
stack.push_back(firstBox);
vector<linkedBoxes*>::iterator iterator = stack.begin();
while (iterator != stack.end()){
if((*iterator)->boxes.size() == 0){
for (int j = 0; j < (*iterator)->points.size(); ++j) {
integPoints.push_back(point + (*iterator)->points[j]);
}
} else {
for (int k = 0; k < (*iterator)->points.size(); ++k) {
Vector3r tmpPoint = point + (*iterator)->points[k];
if(computeDistance(tmpPoint) < 0){
const size_t diff = iterator - stack.begin();
stack.push_back((*iterator)->boxes[k]);
iterator = stack.begin() + diff;
}
}
}
++iterator;
}
Point is a vector which is given to the function and computeDistance returns a value between -1 and 1.
Does somebody knows a way to make this faster?
Bruno
I have a 3D point vector, represented by class Point3D,
std::vector<Point3D> points;
I also have a size_t vector containing indices of the points vector,
std::vector<size_t> indices_true;
Now I want to build the inverse of indices_true, i.e. I want to build another index vector indices_false that contains all indices which are missing in indices_true. How can this be done in a faster way than the following:
for (size_t i = 0; i < points.size(); i++)
{
// TODO: The performance of the following is awful
if (std::find(indices_true.begin(), indices_true.end(), i) == indices_true.end())
indices_false.push_back(i);
}
Needs extra memory, but yields a linear algorithm:
Here is an attempt (neither compiled, nor tested):
indices_false.reserve(points.size() - indices_true.size());
std::vector<char> isTrue(points.size(), false); // avoided std::vector<bool> intentionally
for (const size_t i : indices_true)
{
isTrue[i] = true;
}
for (size_t i = 0; i < points.size(); ++i)
{
if (!isTrue[i])
indices_false.push_back(i);
}
Sort your indices_true vector first and use std::binary_search. To keep the orders within vector using std::stable_sort.
std::stable_sort(indices_true.begin(), indices_true.end());
for (size_t i = 0; i < points.size(); i++)
{
if (std::binary_search(indices_true.begin(), indices_true.end(), i))
indices_false.push_back(i);
}
Sort indices_true and gradually increase an index k within this sorted vector. Increase it when necessary. This yields (beside the initial sorting) a linear algorithm.
Here is an attempt (neither compiled, nor tested):
std::sort(begin(indices_true), end(indices_true));
indices_false.reserve(points.size() - indices_true.size());
size_t k = 0;
for (size_t i = 0; i < points.size(); ++i)
{
if (k < indices_true.size() && i > indices_true[k])
++k;
assert(k >= indices_true.size() || i <= indices_true[k]);
if (k >= indices_true.size() || i != indices_true[k])
indices_false.push_back(i);
}
}
I have a probably very simple question but I can't see the solution.
First, I have a struct named Seed with the following code:
struct Seed
{
int x, y;
int i, j;
int Type;
};
I then create a 2D array and a queue, respectively, like so:
Seed Grid[ROW][COL];
std::queue<Seed> SeedsToUpdate;
I populate the grid with a loop:
void CApp::LoopSeeds(int function, int Type)
{
for(int i = 0;i < ROW;i++)
{
for(int j = 0;j < COL;j++)
{
switch (function)
{
case SET:
SetSeed(i, j, Type);
break;
case DRAW:
DrawSeed(i,j);
break;
case GROW:
GrowSeed(i,j,Type);
}
}
}
}
Then, I set individual seeds in the array to other types, such as GREEN. I then fill the queue by going through the array and filling it with all array elements that have the GREEN type:
void CApp::BuildQueue()
{
for(int i = 0;i < ROW;i++)
{
for(int j = 0;j < COL;j++)
{
if (Grid[i][j].Type != SEED_EMPTY)
{
SeedsToUpdate.push(Grid[i][j]);
}
}
}
}
At this point, everything is good (I think). However, what I want to do is the following: for each seed in the queue, edit the neighbouring cells in the array, something like Grid[i+1][j].Type = GREEN;
And here is my problem: how do I do that, given the above code?
Thanks for your patience.
In C++11
for(const Seed& seed: SeedsToUpdate){
if (seed.i + 1 < ROW){
Grid[seed.i+1][seed.j].type = seed.type
}
}
C++03 with Boost
BOOST_FOREACH(const Seed& seed, SeedsToUpdate){
if (seed.i + 1 < ROW){
Grid[seed.i+1][seed.j].type = seed.type
}
}
In C++03 (without Boost)
for(std::queue<Seed>::const_iter it = SeedsToUpdate.begin(); it != SeedsToUpdate.end(); ++it) {
const Seed& seed = *it;
if (seed.i + 1 < ROW){
Grid[seed.i+1][seed.j].type = seed.type
}
}
Also you should be using std::array/boost::array instead of raw arrays.
its pretty straight forward actually. Inside your inner loop, do something line
if (i+1 < ROW) {
Grid[i+1][j].Type = GREEN;
SeedsToUpdate.push(Grid[i+1][j]);
}