while greater than negative number not working - c++

I have a very trivial piece of code that basically needs to count down from a certain number, and use that count as an index to an array.
auto bigSize = BigArray.size() - 1;
while(bigSize > -1) {
auto thing = arr[bigSize ];
bigSize--;
}
However the code never seems to hit anything inside the loop. I've also tried with a for loop:
auto bigSize = BigArray.size() - 1;
for(int i = bigSize ; i >= 0 && i < bigSize ; --i) {
auto thing = arr[i];
}
I feel like I'm doing something incorrect, but I can't seem to find it.

while(bigSize > -1) {
auto thing = arr[bigSize ];
bigSize--;
}
This will never stop. bigSize is unsigned which means it can't contain negative values. The moment bigSize is 0 and you try to decrement it it becomes std::numeric_limits<type>::max(). (underflow, not negative) So it'll keep on looping.
Either change your condition or make bigSize explicitly an int.

std::Container.size() always returns an unsigned number. An unsigned number will always be greater than a negative number, even if you underflow.

Related

Do While loop doesn't repeat loop even if conditions where true

size_t pos = 0;
int n;
char c;
string temp("x^3+4*x^)8");
do
{
pos = temp.find('^',pos);
/*code*/
pos++;
}while(pos <= temp.npos +1);
//if temp.find didn't find '^' it will return npos (2^32)
What it is supposed to do is find ^ in temp and return it's position to pos, do abit of code and increment pos, repeat the loop if the condition is true. Condition is true if pos <= temp.npos+1, i.e it will break from the loop if temp.find() didn't find any ^ in the string.
But when I debug, the debugger goes the the do loop once before exiting, even if the condition is true.
Edit1
What I know is npos = -1 but on my code, when I debug it, it gives me something else.
npos + 1 probably overflows (because I believe it should be something like MAX_UINT) and then it is (of course) smaller than anything.
npos is defined as size_t npos = -1;
npos + 1 causes overflow, and instead of 2^64 it will be zero.
I would suggest checking for pos < temp.length() instead if you want to go this way.
Fix:
Also, you should check for pos = temp.npos immediately after find and call break from cycle to prevent processing position when nothing is found.
npos is the biggest unsigned integer. npos + 1 is zero and pos >= 0. The loop will repeat if temp.find() returns index 0.
You can change your loop to
do {
pos = temp.find('^',pos);
/*code*/
pos++;
} while(pos != temp.npos);
since pos > temp.npos is never possible.

Simple recursive function to determine if two elements are transitively true

newbie here. Even newer to recursion. I'm writing a function for my C++ program, and as you'll be able to tell, I'm a bit clueless when it comes to recursive algorithms. I'd appreciate it greatly if someone could fix my function so I can get it working and perhaps have a better idea how to handle recursion afterward.
My function takes a two-dimensional square array of booleans, and integer i, and an integer array_size as parameters. The function returns a boolean value.
The array is an adjacency matrix that I use to represent a set of conditionals. For example, if the value at [0][3] is true, then 0 -> 3 (if 0, then 3). If [3][7] is true, then 3 -> 7 (if 3, then 7). By the transitive property, 0 -> 7 (if 0, then 7).
The integer i is a particular element in the set of conditionals. The function will return true if this element is transitively connected to the last element in the array. The last element in the array is the integer (array_size - 1),
The integer array_size is the size of each dimension of the square array. If array_size is 20, then the array is 20x20.
The idea of this function is to determine if there is any logical "path" from the first integer element to the last integer element by the transitive property. When the path exists, the function returns true, otherwise, it returns false. The recursive call should allow it to traverse all possible paths, returning true once it finally reaches the last element and false if all paths fail.
For example, if i = 0 and array_size = 10, then the function will return whether or not 0 -> 9 is valid according to the conditionals provided by the matrix and the transitive property.
This is my code so far:
bool checkTransitivity(bool **relations, int i, int array_size){
bool isTransitive = false;
if (i == array_size - 1)
{
isTransitive = true;
}
else
{
for (int j = i; j < array_size; j++){
if (relations[i][j])
{
isTransitive = checkTransitivity(relations, j, array_size);
}
}
}
return isTransitive;
Currently, the function returns true for all input.
Any help at all is appreciated. Thanks in advance!
EDIT: This first part is unnecessary because of your if-else statement. Move on to END OF EDIT.
Let's start with what a base case in a recursive function is:
if (i == array_size - 1)
{
isTransitive = true;
}
Well you do have a base case, but nothing is being returned. You are just setting a flag to true. What you want to do is:
if (i == array_size - 1) {
return true;
}
Now the function will work its way up the recursive stack to return true. END OF EDIT.
But we still need to fix the recursive case:
else {
for (int j = i; j < array_size; j++) {
if (relations[i][j]) {
isTransitive = isTransitive || checkTransitivity(relations, j, array_size);
}
}
}
return isTransitive;
The || means binary OR. So you have the logic right. You want to check each possible path to see if it can get there, but by setting isTransitive to the result of each check, isTransitive is only going to be set to the last call. By doing isTransitive = isTransitive || recursive call, isTransitive will be true as long as one of the calls results in a true value.
The last thing I want to say is a caution: if relations[i][j] == true and relations[j][i] == true, your code will still be in an infinite loop. You must find a way to eliminate the potential backtracking. One way to do this is to create another array that stores which paths you have already checked so you do not infinitely loop.
More information can be found here: Depth First Search
I think all you need is a break condition to stop continuing the loop when you encounter a non-transitive item. See below (haven't tested)
bool checkTransitivity(bool **relations, int i, int array_size){
bool isTransitive = false;
if (i == array_size - 1)
{
isTransitive = true;
}
else
{
for (int j = i; j < array_size; j++){
isTransitive = relations[i][j] && checkTransitivity(relations, j, array_size);
if (!isTransitive)
break;
}
}
return isTransitive;
}

Initializing An Array with a Variable Size

I am almost done with my code except I need help on two thing. Here is my code: Code. For the function below, I am trying to make it so that I can use the input of "n" to initialize my array, myBits, instead of a constant, which is currently 5.
My Other question is right below that. I am trying to switch all of the right most bits to "true". I wrote the for loop in "/* .....*/" but it doesn't seem to be working. Right above it, I do it long ways for C(5,4) ....(myBit[0] = myBit[1]....etc...... (I am using this to find r-combinations of strings).... and it seems to work. Any help would be appreciated!!
void nCombination(const vector<string> &Vect, int n, int r){
bool myBits[5] = { false }; // everything is false now
myBits[1] = myBits[2] = myBits[3] = myBits[4] = true;
/* for(int b = n - r - 1; b = n - 1; b++){
myBits[b] = true; // I am trying to set the r rightmost bits to true
}
*/
do // start combination generator
{
printVector(Vect, myBits, n);
} while (next_permutation(myBits, myBits + n)); // change the bit pattern
}
These are called variable length arrays (or VLAs for short) and they are not a feature of standard C++. This is because we already have arrays that can change their length how ever they want: std::vector. Use that instead of an array and it will work.
Use std::vector<bool>:
std::vector<bool> myBits(n, false);
Then you have to change your while statement:
while (next_permutation(myBits.begin(), myBits.end()));
You will also have to change your printVector function to take a vector<bool>& as the second argument (you won't need the last argument, n, since a vector knows its own size by utilizing the vector::size() function).
As to your program: If you're attempting to get the combination of n things taken r at a time, you will need to write a loop that initializes the last right r bools to true instead of hard-coding the rightmost 4 entries.
int count = 1;
for (size_t i = n-1; i >= 0 && count <= r; --i, ++count)
myBits[i] = true;
Also, you should return immediately from the function if r is 0.

Random choices of two values

In my algorithm I have two values that I need to choose at random but each one has to be chosen a predetermined number of times.
So far my solution is to put the choices into a vector the correct number of times and then shuffle it. In C++:
// Example choices (can be any positive int)
int choice1 = 3;
int choice2 = 4;
int number_of_choice1s = 5;
int number_of_choice2s = 1;
std::vector<int> choices;
for(int i = 0; i < number_of_choice1s; ++i) choices.push_back(choice1);
for(int i = 0; i < number_of_choice2s; ++i) choices.push_back(choice2);
std::random_shuffle(choices.begin(), choices.end());
Then I keep an iterator to choices and whenever I need a new one I increase the iterator and grab that value.
This works but it seems like there might be a more efficient way. Since I always know how many of each value I'll use I'm wondering if there is a more algorithmic way to go about doing this, rather than just storing the values.
You are unnecessarily using so much memory. You have two variables:
int number_of_choice1s = 5;
int number_of_choice2s = 1;
Now simply randomize:
int result = rand() % (number_of_choice1s + number_of_choice2s);
if(result < number_of_choice1s) {
--number_of_choice1s;
return choice1;
} else {
--number_of_choice2s;
return choice2;
}
This scales very well two millions of random invocations.
You could write this a bit more simply:
std::vector<int> choices(number_of_choice1s, choice1);
choices.resize(number_of_choice1s + number_of_choice2s, choice2);
std::random_shuffle(choices.begin(), choices.end());
A biased random distribution will keep some kind of order over the resulting set ( the choice that was picked the most have lesser and lesser chance to be picked next ), which give a biased result (specially if the number of time you have to pick the first value is large compared to the second value, you'll endup with something like this {1,1,1,2,1,1,1,1,2}.
Here's the code, which looks a lot like the one written by #Tomasz Nurkiewicz but using a simple even/odd which should give about 50/50 chance to pick either values.
int result = rand();
if ( result & 1 && number_of_choice1s > 0)
{
number_of_choice1s--;
return choice1;
}else if (number_of_choice2s>0)
{
number_of_choice2s--;
return choice2;
}
else
{
return -1;
}

Reversing for loop causing system errors

This feels like a newbie issue, but I can't seem to figure it out. I want to iterate over the items in a std::vector. Currently I use this loop:
for (unsigned int i = 0; i < buffer.size(); i++) {
myclass* var = buffer.at(i);
[...]
}
However, I realised that I actually want to iterate over it in the opposite order: starting at the end and working my way to 0. So I tried using this iterator:
for (unsigned int i = buffer.size()-1; i >= 0; i--) {
myclass* var = buffer.at(i);
[...]
}
But by simply replacing the old line with the new (and of course, recompiling), then it goes from running properly and iterating over the code, it instead causes the program to crash the first time it hits this line, with this error:
http://i43.tinypic.com/20sinlw.png
Followed by a "[Program] has stopped working" dialog box.
The program also returns exit code 3, according to Code::Blocks, which (if this article is to be believed) means ERROR_PATH_NOT_FOUND: The system cannot find the file specified.
Any advice? Am I just missing something in my for loop that's maybe causing some sort of memory issue? Is the return code of 3, or the article, misleading, and it doesn't actually mean "path not found"?
An unsigned integer is always >= 0. Furthermore, decrementing from 0 leaps to a large number.
When i == 0 (i.e. what should be the last iteration), the decrement i-- causes i to wrap around to the largest possible value for an unsigned int. Thus, the condition i >= 0 still holds, even though you'd like the loop to stop.
To fix this, you can try something like this, which maintains the original loop logic, but yields a decrementing i:
unsigned int i;
unsigned int size = buffer.size();
for (unsigned int j = 0; j < size; j++) {
i = size - j - 1;
Alternatively, since std::vector has rbegin and rend methods defined, you can use iterators:
for(typename std::vector<myclass *>::reverse_iterator i = buffer.rbegin(); i != rend(); ++i)
{
myclass* var = *i;
// ...
}
(There might be small syntactic errors - I don't have a compiler handy)
#include <vector>
using namespace std;
int main() {
vector<int> buffer = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (vector<int>::reverse_iterator it = buffer.rbegin(); it != buffer.rend(); it++) {
//do your stuff
}
return 0;
}