Removing first three elements of 2d array C++ - c++

So here's my problem.. I have a 2d array of 2 char strings.
9D 5C 6S 9D KS 4S 9D
9S
If 3 found I need to delete the first 3 based on the first char.
card
My problem is I segfault almost anything i do...
pool is the 2d vector
selection = "9S";
while(col != GameBoard::pool.size() ){
while(GameBoard::pool[col][0].at(0) == selection.at(0) || cardsRem!=0){
if(GameBoard::pool[col].size() == 1){
GameBoard::pool.erase(GameBoard::pool.begin() + col);
cardsRem--;
}
else{
GameBoard::pool[col].pop_back();
cardsRem--;
}
}
if(GameBoard::pool[col][0].at(0) != selection.at(0)){
col++;
}
}
I've tried a series of for loops etc, and no luck! Any thoughts would save my sanity!
So I've tried to pull out a code segment to replicate it. But I can't...
If I run my whole program in a loop it will eventually throw a segfault. If I run that exact code in the same circumstance it doesn't... I'm trying to figure out what I'm missing. I'll get back in if I figure out exactly where my issue is..
So in the end the issue is not my code itself, i've got memory leaks or something somewhere that are adding up to eventually crash my program... That tends to be in the same method each time I guess.

The safer and most efficient way to erase some elements from a container is to apply the erase-remove idiom.
For instance, your snippet can be rewritten as the following (which is testable here):
using card_t = std::string;
std::vector<std::vector<card_t>> decks = {
{"9D", "5C", "6S", "9D", "KS", "4S", "9D"},
{"9S"}
};
card_t selection{"9S"};
// Predicate specifing which cards should be removed
auto has_same_rank = [rank = selection.at(0)] (card_t const& card) {
return card.at(0) == rank;
};
auto & deck = decks.at(0);
// 'std::remove_if' removes all the elements satisfying the predicate from the range
// by moving the elements that are not to be removed at the beginning of the range
// and returns a past-the-end iterator for the new end of the range.
// 'std::vector::erase' removes from the vector the elements from the iterator
// returned by 'std::remove_if' up to the end iterator. Note that it invalidates
// iterators and references at or after the point of the erase, including the
// end() iterator (it's the most common cause of errors in code like OP's).
deck.erase(std::remove_if(deck.begin(), deck.end(), has_same_rank),
deck.end());

So for anyone else in the future who comes across this...
The problem is I was deleting an element in the array in a loop, with the conditional stop was it's size. The size is set before hand, and while it was accounted for in the code it still left open the possibility for while(array.size() ) which would be locked in at 8 in the loop be treated as 6 in the code.
The solution was to save the location in the vector to delete and then delete them outside of the loop. I imagine there is a better, more technical answer to this, but it works as intended now!
for (double col = 0; col < size; ++col)
{
if(GameBoard::pool[col][0].at(0) == selection.at(0)){
while(GameBoard::pool[col][0].at(0) == selection.at(0) && cardsRem !=0){
if( GameBoard::pool[col].size() > 1 ){
GameBoard::pool[col].pop_back();
cardsRem--;
}
if(GameBoard::pool[col].size() <2){
toDel.insert ( toDel.begin() , col );
//GameBoard::pool.erase(GameBoard::pool.begin() + col);
cardsRem--;
size--;
}
}
}
}
for(int i = 0; i< toDel.size(); i++){
GameBoard::pool.erase(GameBoard::pool.begin() + toDel[i]);
}

Related

Fast algorithm to remove odd elements from vector

Given a vector of integers, I want to wrote a fast (not obvious O(n^2)) algorithm to remove all odd elements from it.
My idea is: iterate through vector till first odd element, then copy everything before it to the end of vector (call push_back method) and so on until we have looked through all original elements (except copied ones), then remove all of them, so that only the vector's tail survive.
I wrote the following code to implement it:
void RemoveOdd(std::vector<int> *data) {
size_t i = 0, j, start, end;
uint l = (*data).size();
start = 0;
for (i = 0; i < l; ++i)
{
if ((*data)[i] % 2 != 0)
{
end = i;
for (j = start, j < end, ++j)
{
(*data).push_back((*data)[j]);
}
start = i + 1;
}
}
(*data).erase((*data).begin(), i);
}
but it gives me lots of errors, which I can't fix. I'm very new to the programming, so expect that all of them are elementary and stupid.
Please help me with error corrections or another algorithm implementation. Any suggestions and explanations will be very appreciative. It is also better not to use algorithm library.
You can use the remove-erase idiom.
data.erase(std::remove_if(data.begin(), data.end(),
[](int item) { return item % 2 != 0; }), data.end());
You don't really need to push_back anything (or erase elements at the front, which requires repositioning all that follows) to remove elements according to a predicate... Try to understand the "classic" inplace removal algorithm (which ultimately is how std::remove_if is generally implemented):
void RemoveOdd(std::vector<int> & data) {
int rp = 0, wp = 0, sz = data.size();
for(; rp<sz; ++rp) {
if(data[rp] % 2 == 0) {
// if the element is a keeper, write it in the "write pointer" position
data[wp] = data[rp];
// increment so that next good element won't overwrite this
wp++;
}
}
// shrink to include only the good elements
data.resize(wp);
}
rp is the "read" pointer - it's the index to the current element; wp is the "write" pointer - it always points to the location where we'll write the next "good" element, which is also the "current length" of the "new" vector. Every time we have a good element we copy it in the write position and increment the write pointer. Given that wp <= rp always (as rp is incremented once at each iteration, and wp at most once per iteration), you are always overwriting either an element with itself (so no harm is done), or an element that has already been examined and either has been moved to its correct final position, or had to be discarded anyway.
This version is done with specific types (vector<int>), a specific predicate, with indexes and with "regular" (non-move) assignment, but can be easily generalized to any container with forward iterators (as its done in std::remove_if) and erase.
Even if the generic standard library algorithm works well in most cases, this is still an important algorithm to keep in mind, there are often cases where the generic library version isn't sufficient and knowing the underlying idea is useful to implement your own version.
Given pure algorithm implementation, you don't need to push back elements. In worst case scenario, you will do more than n^2 copy. (All odd data)
Keep two pointers: one for iterating (i), and one for placing. Iterate on all vector (i++), and if *data[I] is even, write it to *data[placed] and increment placed. At the end, reduce length to placed, all elements after are unecessary
remove_if does this for you ;)
void DeleteOdd(std::vector<int> & m_vec) {
int i= 0;
for(i= 0; i< m_vec.size(); ++i) {
if(m_vec[i] & 0x01)
{
m_vec.erase(m_vec.begin()+i);
i--;
}
}
m_vec.resize(i);
}

Bubble sort algorithm not working

I am in the process of creating a C++/SFML game engine. Every "entity" in the game has a pointer to it stored in a static vector in the Entity class, called entityRenderList. This vector is sorted by the Bubble Sort algorithm on each iteration of the game loop so that the sprites are drawn in the correct order.
Whenever an entity is deleted, it replaces its pointer in the vector with a NULL pointer. My algorithm should, by default, cause any NULL pointers it finds to be sorted to the back of the vector, where they are subsequently removed.
Here is the code for the sorting algorithm:
bool Entity::depthSortFunction(Entity* a, Entity* b)
{
if (b==NULL) return false; //any NULL values are moved to the back
if (a==NULL) return true;
else return (a->depth_) < (b->depth_);
}
void Entity::sortEntityRenderList()
{
if (entityRenderList.size()>1) {
//Any NULL values are brought to the top to be stripped off.
bool passMade=false;
Entity* temp;
int n=entityRenderList.size()-1;
for(int i=0; i<n; i++)
{
passMade=false;
for(int j=0; j<n-1; j++)
{
if(depthSortFunction(entityRenderList[j],entityRenderList[j+1]))
{
//then swap them
temp = entityRenderList[j+1];
entityRenderList[j+1] = entityRenderList[j];
entityRenderList[j] = temp;
//and then notify the entities of the change
if (entityRenderList[j]!=NULL) {entityRenderList[j]->renderListID=j;}
if (entityRenderList[j+1]!=NULL) {entityRenderList[j+1]->renderListID=j+1;}
passMade=true;
//std::cout<<"Swapping entries "<<j<<" and "<<j+1<<"...\n";
}
}
if (!passMade) {
break; //then it is sorted, as we have not needed to modify the array.
}
}
}
//Now, we strip off any NULL values from the top.
while (!entityRenderList.empty() && entityRenderList.back()==NULL) {
entityRenderList.pop_back(); //strip off last one
}
}
What should be happening is that any NULL pointers are removed from the vector on each run of the algorithm. However, this is not the case, and any NULL pointers stay right where they are, and appear to not be sorted at all.
NB: The passMade boolean is there so that if a pass of the array is made and no swaps were made, the algorithm stops.
Any help would be appreciated. Thanks in advance.
EDIT: The sorting algorithm code is slightly modified from here.
There is a bug in the j loop limit. For example, if the list has 10 elements, n is 9, n-1 is 8, and the largest value of j is 7. The loop can exchange elements 7 and 8 of a 10 element list. It cannot exchange the last pair, elements 8 and 9.
As suggested by a comment, it would be better and simpler to use a library sort that is already tested and working. Rather than adjust the renderListID fields as you go along, you could do them all in a single pass through the list at the end. If you do it after popping the NULL elements, you would not need to test for NULL in that loop.
for(int i=0; i<entityRenderList.size(); i++)
{
entityRenderList[i]->renderListID=i;
}

adding dynamic arrays and removing trailing 0's

I am trying to implement this function to add two dynamic a
rrays, however when I implement this into my main it completely crashes, I have no idea why...
I cannot understand why the program shuts down except the exit code on scite says exit code 255. But that is not helpful. Any idea what the problem may be?
For one:
for (int k=0; k<=max; k++)
This goes out of range. Instead allocate memory for [max+1] elements, since there shall be max+1 terms in the polynomial.
sum = new int[ max + 1 ];
Also, the j loop should start from max.
for (j=max; j>0 && sum[j]==0; --j);
You have a typo on this line:
for (j=max-1; j>0 && sum[j]==0; --j);
^here
The next statement int *tmp=sum; does not get executed.
Also the for loop should probably be
for (j=max-1; j>=0 && sum[j]==0; --j)
^ //don't forget the last member
A couple of nice things about C++ is all the standard containers (like std::vector) and standard algorithms available. For example you could use vectors and backwards iterators and std::find_if_not to find the last non-zero value.
Like
// Create a vector of a specific size, and initialize it
std::vector<int> sum(std::max(a->degree, b->degree), 0);
// Fill it up...
// Find the last non-zero value
auto last_non_zero = std::find_if_not(sum.rbegin(), sum.rend(),
[](const int& value){ return value == 0; });
if (last_non_zero == sum.rbegin())
{
// No zeroes found
}
else if (last_non_zero == sum.rend())
{
// All of it was zero
sum.clear();
}
else
{
std::vector<int> temp(last_non_zero, sum.rend())
std::reverse(temp); // Because the `temp` vector is reversed
sum = temp;
}
After this the vector sum should have been stripped of trailing zeroes.

Erasing an element from the vector during iteration c++

I wrote this method to find the minor of a sparse matrix:
SpMatrixVec SparseMatrix::minor(SpMatrixVec matrix, int col) const{
SpMatrixVec::iterator it = matrix.begin();
int currRow = it->getRow();
int currCol = col;
while(it != matrix.end()) {
if(it->getRow() == currRow || it->getCol() == currCol){
matrix.erase(it);
}
// if we have deleted an element in the array, it doesn't advance the
// iterator and size() will be decreased by one.
else{
it++;
}
}
// now, we alter the cells of the minor matrix to be of proper coordinates.
// this is necessary for sign computation (+/-) in the determinant recursive
// formula of detHelper(), since the minor matrix non-zero elements are now
// in different coordinates. The row is always decreased by one, since we
// work witht he first line, and the col is decreased by one if the element
// was located after 'col' (which this function receives as a parameter).
//change the cells of the minor to their proper coordinates.
for(it = matrix.begin(); it != matrix.end(); it++){
it->setRow(it->getRow()-1);
int newY;
newY = (it->getCol() > col) ? it->getCol() + 1 : it->getCol();
it->setCol(newY);
}
return matrix;
}
Now, i'm probably doing something wrong, because when reaching the second interation of the while loop, the program crashes.
The basic idea was to go over the vector, and see if it is the relevant coordinate, and if so - to delete it. I increment the iterator only if there was no deletion (and in this case, the vector should update the iterator to be pointing the next element..unless i got these things wrong).
Where is the problem?
Thanks a lot.
erase() invalidates your iterator.
You must update it using the return value of erase() for the loop to work:
while(it != matrix.end()) {
if(it->getRow() == currRow || it->getCol() == currCol){
//matrix.erase(it);
it = matrix.erase(it); // Here is the change
}
// if we have deleted an element in the array, it doesn't advance the
// iterator and size() will be decreased by one.
else{
//it++;
++it; // ++i is usually faster than i++. It's a good habit to use it.
}
}
erase invalidates your iterator. Do it = matrix.erase(it) instead.
You can't change a collection while you're iterating between its elements.
Use another temp collection to store the partial results.
edit: Even better, use a functor to delete elements: remove_if
You write the condition.

Array PopFront Method C++

Trying not to lose it here. As you can see below I have assigned intFrontPtr to point to the first cell in the array. And intBackPtr to point to the last cell in the array...:
bool quack::popFront(int& nPopFront)
{
nPopFront = items[top+1].n;
if ( count >= maxSize ) return false;
else
{
items[0].n = nPopFront;
intFrontPtr = &items[0].n;
intBackPtr = &items[count-1].n;
}
for (int temp; intFrontPtr < intBackPtr ;)
{
++intFrontPtr;
temp = *intFrontPtr;
*intFrontPtr = temp;
}
return true;
}
In the else statement I'm simply reassigning to ensure that my ptrs are where I want them. For some reason I'm popping off the back instead of off the front.
Anyone care to explain?
I'm not entirely sure I understand what you're trying to do, but if I;m guessing right you're trying to 'pop' the 1st element of the array (items[0]) into the nPopFront int reference, then move all the subsequent elements of the array over by one so that the 1st element is replaced by the 2nd, the 2nd by the 3rd, and so on. After this operation, the array will contain one less total number of elements.
Not having the full declaration of the quack class makes most of the following guesswork, but here goes:
I'm assuming that item[0] represents the 'front' of your array (so it's the element you want 'popped').
I'm also assuming that 'count` is the number of valid elements (so item[count-1] is the last valid element, or the 'back' of the array).
Given these assumptions, I'm honestly not sure what top is supposed to represent (so I might be entirely wrong on these guesses).
Problem #1: your nPopFront assignment is reversed, it should be:
nPopFront = items[0].n;
Problem #2; your for loop is a big no-op. It walks through the array assigning elements back to their original location. I think you want it to look more like:
for (int i = 1; i < count; ++i)
{
items[i-1].n = items[i].n; // move elements from back to front
}
Finally, you'll want to adjust count (and probably top - if you need it at all) before you return to adjust the new number of elements in the data structure. The whole thing might look like:
bool quack::popFront(int& nPopFront)
{
if ( count >= maxSize ) return false;
if ( count == 0 ) return false; // nothing to pop
nPopFront = items[0].n;
intFrontPtr = &items[0].n; // do we really need to maintain these pointers?
intBackPtr = &items[count-1].n;
for (int i = 1; i < count; ++i)
{
items[i-1].n = items[i].n; // move elements from back to front
}
count -= 1; // one less item in the array
return true;
}
The original question seems to be that you don't understand why the function popFront returns 3 times when there are 3 elements?
If that's the case, I think you are missing the point of recursion.
When you make a recursive call, you are calling the same function again, basically creating a new stack frame and jumping back to the same function. So if there are 3 elements, it will recurse by encountering the first element, encountering the second element, encountering the third element, returning from the third encounter, returning from the second encounter, and returning from the first encounter (assuming you are properly consuming your array, which you don't appear to be).
The current function cannot return until the recursive call has iterated, thus it may appear to return from the last element before the second, and the second before the first.
That is how recursion works.
I wasn't able to make sense of your example, so I whipped one up real fast:
#include <iostream>
using namespace std;
bool popfront(int* ptr_, int* back_) {
cerr << ptr_[0] << endl;
if(ptr_ != back_) {
popfront(++ptr_, back_);
}
return true;
}
int main() {
int ar[4] = {4,3,2,1};
popfront(ar, ar + 3);
return 0;
}
That's not great, but it should get the point across.
Can't you just use a std::list?
That makes it really to pop from either end using pop_front or pop_back. You can also add to the front and the back. It also has the advantage that after popping from the front (or even removing from the middle of the list) you don't have to shift anything around (The link is simply removed) which makes it much more efficient than what you are, seemingly, proposing.
I'm assuming you're trying to assign the popped value to nPopFront?
bool stack::popFront(int& nPopFront)
{
//items[4] = {4,3,2,1}
if ( intFrontPtr < intBackPtr )
{
nPopFront = *intFrontPtr;
++intFrontPtr;
}
return true;
}
bool quack::popFront(int& nPopFront)
{
if(items.n==0) throw WhateverYouUseToSignalError;
nPopFront = items[0];
for (int =0;i<items.n-1,++i){
items[i]=items[i+1]
}
//update size of items array
}