Error when applying a function multiple times - c++

I wrote a function to find all combinations of integers between two bounds. To do this, I wrote a function with the same name that finds all combinations of integers between two bounds of a certain size.
In main, I set up a loop to call this function multiple times. When it is ran more than once with bounds that are sufficiently far apart, it causes an error, that is, the code reaches the logic error in the first function.
I do not know why multiple passes in the while-loop causes a problem because the variables should be reset each time.
#include <vector>
#include <stdexcept>
#define VAR1 3
#define VAR2 8
bool nextCombination(std::vector<int> &combo, int numItems, \
int lowerBound, int upperBound) {
if (combo.empty()) { //This is the first take.
for (int i = 0; i < numItems; ++i) {
combo.push_back(lowerBound + i);
}
return true;
} else if (combo[0] >= upperBound - numItems) { //This cleans up.
combo.clear();
return false;
} else {
for (int i = 0; i < numItems; ++i) {
if (i >= numItems || combo[i]+1 != combo[i+1]) {
++combo[i]; //This extends the front of the stack.
return true;
} else { //This pushes the first part of the stack back.
combo[i] = lowerBound + i;
}
}
}
throw std::logic_error("There is an error with nextCombination.");
}
bool nextCombination(std::vector<int> &combo, int lowerBound, int upperBound) {
int numItems = combo.size();
if (numItems >= upperBound - lowerBound) {
combo.clear();
return false;
} else if (numItems == 0) {
combo.push_back(0);
return true;
} else {
if (nextCombination(combo, numItems, lowerBound, upperBound)) {
return true;
} else {
combo.clear(); //This line shouldn't be needed.
return (nextCombination(combo, numItems+1, lowerBound, upperBound));
}
}
}
int main() {
for (int i = 0; i < VAR1; ++i) {
std::vector<int> combo;
while (nextCombination(combo, 0, VAR2)) ;
}
return 0;
}

I don't understand the algorithm, but the problems are clear enough.
Step one, reduce the size of the problem I chose
#define VAR1 1
#define VAR2 2
Run the code, crash in operator[] here,
if (i >= numItems || combo[i]+1 != combo[i+1])
Values of variables
combo = vector of size 1
numItems = 1
i = 0
combo[i+1] is a subscript out of bounds error.
It doesn't take long to step through the code to get to this point. It happens immediately on the second iteration of the inner loop in main. Since I don't understand what your code is trying to do I can't suggest a fix. But hopefully the error is clearer to you now.
Since it seems you were unaware of this subscripting issue, you should change to using at instead of [] that way you get defined behaviour even on a subscript error.

Related

How to remove 'goto' from this loop?

I have a loop that looks for 3 equal cards or 3 non equal cards and erases as it finds, if it doesn't find 2 equals/non-equals for the 1st chosen element it deletes that 1st element and goes to the other and so on...
Well, I'm using goto in this code to break from inside of two for loops and keep iterating throughout while.
To me, it makes good sense to use goto in this specific situation. But, since I'm not a very experienced programmer I think there would be a better way to do it, a more efficient way.
Is there? How would that be? not using goto in this case.
unsigned int i1 = 0;
while(gameCards.size() > 2)
{
for(unsigned int i2=1; i2<gameCards.size(); i2++)
{
if(i2 == 2) continue;
if(cannotMatch(gameCards.at(i1), gameCards.at(i2)))
{
for(unsigned int i3=2; i3<gameCards.size(); i3++)
{
if(cannotMatch3(gameCards.at(i1), gameCards.at(i2), gameCards.at(i3)))
{
SetMatches++;
gameCards.erase(gameCards.begin()+i2,gameCards.begin()+i3);
goto findAnother;
}
}
} else if(canMatch(gameCards.at(i1), gameCards.at(i2)))
{
for(unsigned int i3=2; i3<gameCards.size(); i3++)
{
if(canMatch3(gameCards.at(i1), gameCards.at(i2), gameCards.at(i3)))
{
SetMatches++;
gameCards.erase(gameCards.begin()+i2,gameCards.begin()+i3);
goto findAnother;
}
}
}
}
findAnother:
gameCards.erase(gameCards.begin()+(i1++));
}
You can just set an extra bool condition to break outer for loop. You can also simplify your inner loops when you notice that they are essentially the same, just invoke different match3 functions:
while(gameCards.size() > 2)
{
auto continue_outer_loop(true);
for(unsigned int i2=1; continue_outer_loop && (i2<gameCards.size()); i2++)
{
if(i2 == 2) continue;
auto const p_match_3_func
(
cannotMatch(gameCards.at(i1), gameCards.at(i2))
?
&cannotMatch3
:
&canMatch3
);
for(unsigned int i3=2; i3<gameCards.size(); i3++)
{
if((*p_match_3_func)(gameCards.at(i1), gameCards.at(i2), gameCards.at(i3)))
{
SetMatches++;
gameCards.erase(gameCards.begin()+i2,gameCards.begin()+i3);
continue_outer_loop = false;
break;
}
}
}
gameCards.erase(gameCards.begin()+(i1++));
}
You can add guard variable and check for it in your loops. But will work, only when you do it at the end of loop as it is not real break.
while (mainLoop) {
int goMain = 0;
for (int i = 0; i < 5 && goMain == 0; i++) {
for (int j = 0; j < 5 && goMain == 0; j++) {
if (wantExit) {
goMain = 1;
}
}
}
}

Why does skips the "if stack not empty" conditional, when the stack still has elements?

I'm trying to make a program to solve the eight queens problem, however it keeps reaching the last return, when it should not, and tried putting it on an else, but then it never reached it, even if i initially give it an empty stack.
Also for whatever reasons the first time i call the top() function, it return a different element than the last i added, but if i call it again it return the correct element.
So i would like to know where the problem is?
bool search(stack<nodo>& board, int n) {
nodo queen;
queen=board.top();
queen=board.top();
if (queen.y == n)
return true;
bool valid;
if (!board.empty()) {
queen.y += 1;
for(int i; i<=n; i++) {
queen.x = i;
valid = isvalid(queen,board);
if (valid) {
board.push(queen);
search(board,n);
}
}
board.pop();
}
return false;
}
use while not if
while(!board.empty()) {
queen.y += 1;
for(int i; i<=n; i++){
queen.x = i;
valid = isvalid(queen,board);
if (valid) {
board.push(queen);
search(board,n);
}
}
board.pop();
}
if means check for one time only , but while mean do the samething till board.empty() == true.

C++ Connect 4 Checking Next Step Error

I am writing a Connect 4 game with minimax, but my next-step checking function is sometimes giving me unexpected results. Can you please tell me if my algorithm is correct?
For example if my board looks like this
0000000
0000000
0000000
0000000
1000000
2002120
it will return column 0 as true for player 2.
bool Board::check2(int player, int& bestMove)
{
for (int i=0; i<WIDTH; i++)
{
if(addToColumn(i, player))
{
if (checkNext(2, i, player))
{
bestMove=i;
removeFromColumn(i, player);
return true;
}
removeFromColumn(i, player);
}
}
return false;
}
bool Board::checkNextVertical(int size, int column, int player1)
{
int counter=0;
int player2;
if (player1==1)
{
player2=2;
}
else
player2=1;
for (int i=0 ; i<DEPTH; i++)
{
if (arrBoard[column][i]==player1)
{
counter++;
}
if (arrBoard[column][i]==player2)
{
return false;
}
if (counter==size)
{
return true;
}
}
return false;
}
bool Board::checkNextHorizontal(int size, int column, int player1)
{
int counter=0;
int player2;
if (player1==1)
{
player2=2;
}
else
player2=1;
for (int i=0 ; i<DEPTH; i++)
{
if (arrBoard[i][column]==player1)
{
for (int j = 0; j<WIDTH; j++)
{
if (arrBoard[i][j]==player1)
{
counter++;
}
if (arrBoard[i][j]!=player1)
{
counter=0;
}
if (counter==size)
{
return true;
}
}
}
}
return false;
}
bool Board::checkNext(int size, int column, int player)
{
if (checkNextVertical(size, column, player))
{
// printBoard();
return true;
}
if (checkNextHorizontal(size, column, player))
{
// printBoard();
return true;
}
return false;
}
Welcome to the forum.
There are a few problems with the code you posted:
Your checkNextVertical function appears to be attempting to check horizontally, and your checkNextHorizontal function appears to attempting to check both horizontally and vertically.
If you notice you use both arrBoard[column][i] and arrBoard[i][column]. I'm sure you'll agree only one of these can be correct. It's important to understand which is correct, or else your code will end up attempting to access locations in the array which are not valid, and you will get unexpected behaviour, for example your j loop in the checkNextHorizontal function is currently doing this.
It should be used as array[y / depth / row][x / width / column] - or whatever you will remember.
Personally, this code seems confusing:
int player2;
if (player1==1)
{
player2=2;
}
else
player2=1;
player2=1 seems like trying to push a square peg in a round hole. Could you use int player and set it to either 1 or 2 to make it easier to read?
I totally agree with Joachim - if you have these sorts of problems, it's always a great idea to fill the array with some data, then use the debugger to step through your code and check that the data being accessed is the data you expect to be accessed.
Alternatively, since it's a connect4 game, I assume at some point you know the column which the last move was made, in which case you can use this function to check if it was a winning move. You just need to tell it which column the last move was, and the required 'size' to win. If you do use it, I would still recommend stepping through it with the debugger so you can understand the array access. NB: your code wasn't checking diagonally - so neither does this. Some extra logic required if you want to do that:
bool winningMove(int column, int size)
{
bool winnerWinnerChickenDinner = false;
int player = 0;
int row = 0;
// Who was the last player to go in this column
// i.e. find the top non-zero entry
for (int i = 0; i < DEPTH; i++)
{
if (arrBoard[i][column] != 0)
{
player = arrBoard[i][column];
row = i;
break;
}
}
// If we found a player, check if it was a winning move
if (player != 0)
{
int count = 0;
// Loop twice, first horizontally, then vertically
for (int i = 0; i < 2 && !winnerWinnerChickenDinner; i++)
{
bool horizontal = (i == 0);
for (int j = 0; j < (horizontal ? WIDTH : DEPTH); j++)
{
// Check if we have 'size' consecutive entries by the same player
// (When we check horizontally, use arrBoard[row][j] to check the row)
// (When we check vertically, use arrBoard[j][column] to check the column)
if (arrBoard[(horizontal ? row : j)][(horizontal ? j : column)] == player)
{
if (++count == size)
{
winnerWinnerChickenDinner = true;
break;
}
}
else
{
count = 0;
}
}
}
}
return winnerWinnerChickenDinner;
}
The old games are the best - Connect4 is awesome, so good luck.

Mergesort - std::bad_alloc thrown when trying to assign vector

Good afternoon ladies and gents. So, it is not my day for errors. Implementing Mergesort (not in-place) in C++, and I'm having real trouble with the code, with no idea why. The second-to-last line of the mergeSort() function assigns the result of the merge() to a vector of ints, result. This line (the actual allocation, not the function) throws a bad_alloc error, and I have no idea why.
The internet suggests that bad_alloc is mostly thrown due to out-of-memory errors, but this cannot be the case as the first time its called is on a vector of 500 ints, which should be nowhere near too much memory (what is that, like 2 Kb on a 32-bit int?). I assume I'm doing something silly and incorrect for C++, but I don't know what. I tried calling what() on the exception, but that just returns its name. The code:
vector<int> Sorting::mergeSort(vector<int> A) {
// If the length of A is 0 or 1, it is sorted.
if(A.size() < 2) return A;
// Find the mid-point of the list.
int midpoint = A.size() / 2;
// Declare the left/right vectors.
vector<int> left, right;
// Declare the return vector.
vector<int> result (A.size());
for(int i = 0; i < midpoint; ++i) {
left.push_back(A.at(i));
}
for(int i = midpoint; i < A.size(); ++i) {
right.push_back(A.at(i));
}
left = mergeSort(left);
right = mergeSort(right);
result = merge(left, right);
return result;
}
vector<int> merge(vector<int> left, vector<int> right) {
vector<int> result;
while(left.size() > 0 && right.size() > 0) {
if(left.front() <= right.front()) {
result.push_back(left.front());
left.erase(left.begin());
} else {
result.push_back(right.front());
right.erase(right.begin());
}
}
if(left.size() > 0) {
for(int i = 0; i < left.size(); ++i) {
result.push_back(left.at(i));
}
} else {
for(int i = 0; i < right.size(); ++i) {
result.push_back(right.at(i));
}
}
}
If I re-write the merge function to just take a reference to result and edit it during the function, it works fine, but I wanted to keep the code as close as possible to the 'standard' psuedo-code given for merge-sort.
I appreciate any help, thanks.
In the Merge function, vector<int> result is not being returned.

array loop not working correctly? c++

Trying to count how many elements within the array are not equal to 0, is something set up wrong?
I'd like to check all values in the array (it's a sudoku board) and then when all elements are "full" I need to return true.
Is something off?
bool boardFull(const Square board[BOARD_SIZE][BOARD_SIZE])
{
int totalCount=0;
for (int index1 = 0; index1 < BOARD_SIZE; index1++)
for (int index2 = 0; index2 < BOARD_SIZE; index2++){
if(board[index1][index2].number!=0)
totalCount++;
}
if(totalCount=81)
return true;
else
return false;
You have = rather than ==
if (totalCount == 81)
is the correct line.
Doing this with a single "=" actually assigns the value 81 to totalCount, so your test is essentialy:
if (81)
And since in C++ anything nonzero is true, this is always true
You have a = that should be a ==. That's all I'll say, since it's homework.
Also, why do you have a constant for BOARD_SIZE, then check against 81 at the end? Wouldn't checking against BOARD_SIZE * BOARD_SIZE be better?
Is the If(totalCount=81) a typo in this post or your code? Looks like you've assigned the value there.
You can leave the function as soon as you find the first 0, and it's possible to solve this with a single loop:
bool boardFull(const Square board[BOARD_SIZE][BOARD_SIZE])
{
const Square* p = board[0];
for (int n = BOARD_SIZE * BOARD_SIZE; n; --n, ++p)
{
if (p->number == 0) return false;
}
return true;
}
But I prefer algorithms to hand-written loops:
struct Square
{
int number;
bool is_zero() const
{
return number == 0;
}
};
#include <algorithm>
#include <functional>
bool boardFull(const Square board[BOARD_SIZE][BOARD_SIZE])
{
return std::find_if(
board[0],
board[BOARD_SIZE],
std::mem_fun_ref(&Square::is_zero)
)== board[BOARD_SIZE];
}