Iterator and reverse Iterator - c++

I am quiet fresh to C++ and programming in general, I am writing an OpenCv application in C++ environment.
WHAT I AM TRYING TO ACHIEVE:
OK, so I got some Rectangles center points stored in a vector, Now I am using a reverse Iterator to iterate over the vector with rectangle center points and store every 10th center point into new vector.
I then again iterate over that new vector that stores every 10th rectangle center point with normal iterator, And I want to subtract 1st element from 2nd element 3rd element from 4th element and so on, the subtraction results, I want to store into another new vector :D
It might be slightly confusing to some people; I am confused, myself, that is why below I will add the code I have written.
vector<Point> Rightarm;
vector<Point> Leftarm;
vector<Point>::reverse_iterator RightMovmentIter;
vector<Point>::reverse_iterator LeftarmMovmentIter;
vector<Point> RightTracking;
vector<Point> LeftTracking;
for(RightMovmentIter = Rightarm.rbegin(); RightMovmentIter != Rightarm.rend(); RightMovmentIter+=10)
{
RightTracking.push_back(*RightMovmentIter);
}
for(LeftarmMovmentIter = Leftarm.rbegin(); LeftarmMovmentIter != Leftarm.rend(); LeftarmMovmentIter+=10)
{
LeftTracking.push_back(*LeftarmMovmentIter);
}
vector<Point>::iterator RresultIter;
vector<Point>::iterator Leftresult_Iter;
vector<Point> summery;
for(RresultIter = RightTracking.begin(); RresultIter != RightTracking.end(); RresultIter++)
{
summery = *RresultIter - *RresultIter++;
}
PROBLEMS:
1st Problem is that when I run the program I get run time error I belief it's because at the begining of the vector Rightarm & Leftarm do not have 10 elements and when the Iterator runs through it and is trying to look for the 10th element i cant....HOW do I work this out then?
2nd Problem is to do with this line summery = *RresultIter - *RresultIter++; I know it's wrong and this is the best attempt I could of think of, but what I want to do is to subtract 1st element from 2nd element and store it in summery element...
Hopefully This describes my problem well enough for the readers
Regards

As you've correctly noticed, this won't work unless Rightarm.size() is an exact multiple of 10. One way to work around this is to skip elements at the beginning, to make the end line up.
for(RightMovmentIter = Rightarm.rbegin() + Rightarm.size() % 10;
RightMovmentIter != Rightarm.rend();
RightMovmentIter+=10)
As for taking the running difference, there's a standard algorithm for that, std::adjacent_difference.
std::adjacent_difference( RightTracking.begin(), RightTracking.end(),
std::back_inserter( summery ) );
summery.erase( summery.begin() );
This copies the first value without taking a difference (similar to assuming the "before-the-first" value is zero) so the erase() line gets rid of that.

Related

What is the best way to get a permutation index list of a given vector

In my application I solve a geometric problem on a given list of points.
0 x0 y0
1 x1 y1
...
The solution file should contain a specific ordering of the points which are represented as a list of their indexes.
1
0
...
After solving the problem I have a result = std::vector<Point>() vector of point objects in a certain order as well as the original list of points as an original = std::vector<Point>() vector. Both vectors naturally have the same size. To generate the output file I go through the result vector and search for the index of the point in the original vector. This is quite inefficient because it does need O(n^2) time. As a slight improvement I do the following:
std::ofstream out(filename);
std::vector<int> indices(instance.size);
std::iota(indices.begin(), indices.end(), 0);
for(auto &point : instance.result.points)
{
for(std::size_t i=0; i<indices.size(); i++)
{
int id = indices[i];
if(point == instance.points[id])
{
out << id << std::endl;
indices.erase(indices.begin()+i);
break;
}
}
}
out.close();
This allows me to not revisit the points that I already found before. Sadly for a 1 million point instance, this process exceeds my time limit and I don't want the export of my solution to take more time than solving the problem itself. Is there a way to efficiently get the indexes of a premutation of some vector in C++? The solution can use a lot of memory if desired.
One of the simple to implement and quite efficient solution is to create a temporary std::unordered_map<Point,size_t> where key is the point and value is position inside original, then do lookup in that map. Details on how to use your (or library provided) data type as a key in std::unordered_map provided here
You can extend the Point structure to contain the original id, besides the position.

Program crashes when attempting to erase the last std::vector element

I'm iterating through the vector std::vector<Bullet*> bullets, and I'm looking for collisions with an enemy. It works great in every case, except for the case when: the last fired bullet (there has to be more than one) collides with the enemy.
Code-
for(std::vector<Bullet*>::iterator it = bullets.begin(); it != bullets.end(); ++it)
{
if ((*it)->getSprite()->getGlobalBounds().intersects(enemy->getSprite()->getGlobalBounds()))
{
delete *it;
bullets.erase(it);
enemy->destroy();
if (bullets.size() == 0)
break;
}
}
I commented particular elements in the for loop, and found out that the bullet.erase(it) call crashes the program.
When that crash happens, I receive a return code: 134 (0x86). What's the issue for that code?
(*it)->getSprite() returns a pointer to a sprite from Bullet class.
What about using remove_if and erase combo:
auto is_hit = [&enemy](Bullet *bullet)
{
if (bullet->getSprite()->getGlobalBounds().intersects(enemy->getSprite()->getGlobalBounds()))
{
delete bullet;
enemy->destroy();
return true;
}
return false;
};
bullets.erase(std::remove_if(bullets.begin(), bullets.end(), is_hit), bullets.end());
For your consideration:
The following code snippet shows how I clean a vector from its tail (the complementary action to adding element to the tail with push_back())
while(!gBoard.empty())
{
Cell_t* cell = gBoard.back(); // fetch last element (a ptr)
gBoard.pop_back(); // remove last element
delete cell; // remove cell from heap - raw pointer
}
Perhaps you could do this style of clean and use multiple vectors ... it still might be faster than alternatives.
In your problem, each bullet appears to have at least two destinations ... hit or miss.
while ( ! Bullets.empty() ) // spin through bullet list
{
Bullet* aBullet = Bullets.back(); // fetch copy of last element
Bullets.pop_back(); // remove last element
if (*aBullet)-> getSprite()->getGlobalBounds().
intersects(enemy->getSprite()->getGlobalBounds()))
{
// HIT!
Hit.push_back(aBullet); // capture the element to Hit bucket
enemy->destroy(); // tbd - a decision? or always final?
// no delete
if (bullets.size() == 0) // no more to compute, redundant to while
break;
}
else
{
// MISS
Missed.push_back(aBullet); // capture element to Missed bucket
}
} // while
assert(bullets.empty()); // bullets have been consumed
// clean up spent bullets that intersected
while (! Hit.empty() )
{
Bullet* aBullet = Hit.back(); // copy last element from Hit
Hit.pop_back(); // remove last element from Hit
delete aBullet; // tbr - delete the dynamic memory
}
// clean up spent bullets that missed
// move the bullet from Missed vec back into Bullets vec
// for tbd - furthur evaluation ... did the bullet hit any other obj
// the following also happens to 'undo' the seq reversal
while (! Missed.empty() )
{
Bullets.push_back (Missed.back()); // copy last element from Missed
Missed.pop_back(); // remove last element from Missed
// tbd - also delete the missed bullet?
// or do you check for these bullets to collide with other objects
}
// possibly a copy can do this last loop, but this is simple and
// undoes the reversal.
and found out that the bullet.erase(it) call [for that last element]
crashes the program
In some sense, you are probably performing the erase prematurely.
Consider the following:
It is possible that the test parameters of range, target, and weapon-type might combine to achieve, for example, a 10% hit ratio. Thus, in a collection of 1000 shots, (1000 == bullets.size()), there would be (~) 100 bullets that have hit the target.
Your code finds each of the elements, and creates 100 'holes' in the vector by using bullets.erase(). Because the vector data is maintained contiguous, the erase method also moves other elements to fill the holes created by erase. (The details of how might differ between implementations.)
Generally, 100 erases causes 100 shuffles of less than (at-most) 1000 elements each time ... this one-at-a-time-approach would probably be a comparatively 'slow' process.
As an alternative to the current design, instead of find-and-erase, defer the erase until your code has identified and marked all 'intersects'.
you can find the intersects (hits) in the same way, but 'mark' them, don't erase them yet. Options include adding a bool to the Bullet class, or maintaining a matching bool vector to hold this flag for each bullet.
Using two indexes,
-- i1 initialized to 0 (first (left most) vector element) and
-- i2 initialized to (bullets.size() - 1) [last (right most) vector element]
-- Spin increment i1 to find the first hit,
-- Spin decrement i2 to find the last miss,
-- then std::swap (bullets[i1], bullets[i2])
Repeat until i1 >= i2
Now that all the hits are contiguous AND at the tail of the vector, perform a single erase of the 100 hits
This should eliminate any shuffling.
Also, there should be no use of an erased element ... because the erase occurs at the end of the process.

QHashIterator in c++

I developed a game in C++, and want to make sure everything is properly done.
Is it a good solution to use a QHashIterator to check which item in the list has the lowest value (F-cost for pathfinding).
Snippet from my code:
while(!pathFound){ //do while path is found
QHashIterator<int, PathFinding*> iterator(openList);
PathFinding* parent;
iterator.next();
parent = iterator.value();
while(iterator.hasNext()){ //we take the next tile, and we take the one with the lowest value
iterator.next();
//checking lowest f value
if((iterator.value()->getGcost() + iterator.value()->getHcost()) < (parent->getGcost() + parent->getHcost())){
parent = iterator.value();
}
}
if(!atDestionation(parent,endPoint)){ //here we check if we are at the destionation. if we are we return our pathcost.
clearLists(parent);
filllists(parent,endPoint);
}else{
pathFound = true;
while(parent->hasParent()){
mylist.append(parent);
parent = parent->getParent();
}
pathcost = calculatePathCost(mylist); //we calculate what the pathcost is and return it
}
}
If no? Are there better improvements?
I also found someting about the std::priority_queue. It this mutch better then a QHashIterator?
It's maybe not a problem with gameworld where there which are not big. But i'm looking for a suitable solution when the game worlds are big (like + 10000 calculations).Any marks?
Here you basically scan the whole map to find the element that is the minimum one according to some values:
while(iterator.hasNext()){ //we take the next tile, and we take the one with the lowest value
iterator.next();
//checking lowest f value
if((iterator.value()->getGcost() + iterator.value()->getHcost()) < (parent->getGcost() + parent->getHcost())){
parent = iterator.value();
}
}
All this code, if you had an stl container, for instance a map, could be reduced to:
auto parent = std::min_element(iterator.begin(), iterator.end(), [](auto& lhs, auto& rhs)
{ lhs.value()->getGcost() + lhs.value()->getHcost()) < (rhs.value()->getGcost() + rhs.value()->getHcost() }
Once you have something easier to understand you can play around with different containers, for instance it might be faster to hold a sorted vector in this case.
)
Your code does not present any obvious problems per se, often performance gains are not conquered by optimizing little loops, it's more on how you code is organized. For instance I see that you have a lot of indirections, those cost a lot in cache misses. Or if you have to always find the minimum element, you could cache it in another structure and you would have it at a constant time, all the time.

What's the proper the structure for storing a big array which will be frequently updated

I'm seeking for a proper structure for a big array which will be frequently updated. Thanks for your help!
Here's the background:
I want to draw a continuous curve to represent a sound wave in a certain time period. For the accuracy, the array length will be nearly 44100(the CD format).And I just want to represent the last second wave, so the array will be updated very frequently - for every 1/44100 sec, the first element will be eliminated and a new last element will be inserted to the array.
For avoiding the frequent "malloc/realloc/new", what my current solution is using an Circular Queue which has a fixed size as 44100, but somehow I don't feel this is most proper solution, if I want to dynamically resize the queue, it will be a heavy cost.
This kind of situation should be quite often, I think there maybe some good patent for this issue.
Thanks guys!
I assume you're always having a fixed number of items in the array. As such I'd just use a ring buffer in any case (not sure whether that's what you refer to as a "Circular Queue", but I assume you'd use a dynamic length? If so, why? Is there no specific absolute (and practical) maximum?), i.e. a static array with a variable entry point as its start:
const unsigned int buffer_length = 500000;
float *buffer = new float[buffer_length];
unsigned int buffer_write = 0;
// append a value...
buffer[buffer_write] = my_value;
// ...and move the write/end position:
buffer_write = (buffer_write + 1) % buffer_length;
To output/use the values, you can use the following formula for index of the first entry to read:
unsigned int start_position = (buffer_length + buffer_write - length_to_read) % buffer_length;
To iterate, you just add position after position, again using modulo to jump back to the beginning of the array.

Insert into a desired element of an array and push all other elements one spot over in c++

Having some issues with one small function I'm working on for a homework assignment.
I have a static array size of 20 (shelfSize), however, I only need to use a max of 10 elements. So I don't have to worry about out of bounds etc (the entire array of 20 is initialized to 0).
What I am looking to do is insert an integer, booknum, into an element of an array it receives as input.
This my current logic:
void insert_at(int booknum, int element){
for(int i=element+1; i < shelfSize; i++)
bookshelf[i+1]=bookshelf[i]
bookshelf[element]=booknum;
}
so let's say I have the this array:
[5,4,3,1,7]
I want to insert an 8 at element 1 and have the array turn to:
[5,8,4,3,1,7]
Technically, everything after the final element 7 is a 0, however, I have a separate print function that only prints up to a certain element.
No matter how many times I take some pencil and paper and manually write out my logic, I can't get this to work.
Any help would be appreciated, thanks.
You should start from the end of the array, this should word for you:
void insert_at(int booknum, int element)
{
for (int i = shelfsize-1;i>element;i--)
bookshelf[i] = bookshelf[i-1];
bookshelf[element] = booknum;
}
Also I recommend that you get used to handling illegal values, for example, what if a user entered 21?
The optimized code would be:
bool insert_at(int booknum, int element)
{
if (element>=shelfsize-1)
return false;
for (int i = shelfsize-2;i>element;i--)
bookshelf[i] = bookshelf[i-1];
bookshelf[element] = booknum;
return true;
}
If your example is correct, then you're assuming 1-based indices instead of 0-based. Use the following instead:
void insert_at(int booknum, int element){
for(int i=element; i < shelfSize; i++)
bookshelf[i]=bookshelf[i-1];
bookshelf[element-1]=booknum;
}
However, I would prefer you just use the same code, and change "at element 2" in your example to "at element 1". Always remember C++ arrays are 0-based.
That being said, please tell your professor that this is why vectors (and other standard containers) were made, and that C++ arrays are evil.
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.1
Just noticed, you are copying up, this means your function does this:
[5,4,3,1,7]
--^
[5,4,4,1,7]
--^
[5,4,4,4,7]
--^
[5,4,4,4,4]
--^
[5,4,4,4,4,4]
For moving values in an array, you always want to copy in the opposite direction to which you are moving, so to move up, you want to copy each item up from the top down:
[5,4,3,1,7]
--^
[5,4,3,1,7,7]
--^
[5,4,3,1,1,7]
--^
[5,4,3,3,1,7]
--^
[5,4,4,3,1,7]
And then you can overwrite the index you freed up.