Why is this loop infinite? - c++

I have some code for drawing polygons edges that is supposed to draw, for example, in a triangle with vertices 0, 1, and 2, the edges (0, 1), (1, 2), and (2, 0). I thought I could accomplish this like so:
for(size_t j = 0, k = 1; j <= vertices.size()-1; j++, k++){
if(j == vertices.size()-1){k = 0;} //For j to k final edge
...
//draw edges, etc.
...
}
...But this makes the k value explode into an infinite loop. I have looked this over and suspect that the problem could be in my indexing here, but if everything depends on j, I would think that maybe vertices.size() is messed up. Am I missing something in this code, or should I look more closely at the actual vertices vector?

You don't need to count over k :
size_t const count = vertrices.size()
for(size_t j = 0; j < count; j++) {
size_t k = (j + 1) % count;
// draw
}
This way k is j+1 except when j is the max, in that case it's 0.

If you do not make sure that vertices has at least one entry the subtraction vertices.size()-1 could lead to underflow (i.e. a very large value from the subtraction size_t(0)-1) and your loop could run much longer than you want.
A more idiomatic solution would be to loop
for (size_t j = 0, k = 1; j < vertices.size(); j++, k++) {
if ( j == vertices.size()-1) { //works, vertices has at least one entry
k = 0;
}
...
//draw edges, etc.
...
}

If vector "vertices" is empty, the loop will be approximately infinite. You are using unsigned integer arithmetic in the condition, so -1 will be 0xFFFFFFF or larger.

It wont be infinite loop if everything other than you gave here is correct. So best answer is check your other parts of code carefully.

Related

Why am I getting a segmention fault?

For my class, we are using two compilers, xcode and codeboard, where codeboard is the more rigorous of the two and has a list of preset asserts to test your code. In my code for function a, I have nested loops, where I want i to always be one ahead of k. It works fine in xcode, but gives me a segmentation fault on codeboard.
for (int k = 0; k <= n-2; k++) {
for (int i = k+1; i <= n-1; i++) {
if (array[k] == array[i])
What's strange is if I use k++ or ++k instead of k+1, it won't result in a segmentation fault, but my code won't pass all the asserts. I thought they were supposed to be the same thing?
What's even more strange is if I use k+1 in function b, it doesn't result in an error in codeboard.
for (int k = 0; k <= n-1; k++) {
for (int i = k+1; i <= n-1; i++) {
if (array[k] > array[i])
Basically, what is happening here?
Edit: So, what I'm getting from everyone is that when I use i = k+1 in the inner loop, it increases the k value in the outer loop. Like, if k=1, i=2, then when it goes back to the outer loop, k=3. If that's the case, how would I get i from staying ahead of k?
Edit: Please ignore the k++ and k+1 part of my question, that was not really my main issue, just a side thing that kind of confused me, but I get the difference now. I'd delete that part from my post, but I'm pretty sure that's not allowed. My main question is how to keep my i value 1 greater than my k value.
In the following code, the goal is if any of the array values are the same, it should cout true at some point. In regards to reproducible results:
string a[3] = {"aaa", "bbbb", "cccc"};
int n = 3;
for (int k = 0; k <= n-2; k++) {
int b = 0;
for (int i = k+1; i <= n-1; i++) {
if (a[k] == a[i])
b++;
}
if (b != 0) {
cout << "true" << endl;
break;
}
else
cout << "false" << endl;
}
No, they're not the same:
k + 1
Returns the value of k plus one, but does not change the value of k itself.
++k
Adds 1 to k and returns the new value (pre-increment).
k++
Also adds 1 to k but returns the previous value of k (post-increment).
k++ and ++k both increase k by one, changing the value of k.
k+1 does not.
Your segmentation fault comes from the fact that you are increasing k every time your initial for-loop is evaluated but also every time your second for loop is initialized. This means that you're reading further than your array at the end of your loop.
k++ and k+1 are not the same.
If you use k++ instead of k+1 inside the loop in the code you have shown, you are actually performing two increments on the variable k, which is usually not what you want in the control variable of a loop.
K+1 does not alter the value of k.
k++ increments k after using its value.
++k increments k before using its value.
So basically what is happening is that every time you start the inner loop, k gets incremented. But in the last round of the external loop, when k is equal to n-1, you perform another increment, which sets k to n, and this is most certainly not what you wanted.

How to Compare multiple variables at the same time in the C++?

I'm making Sudoku validater program that checks whether solved sudoku is correct or not, In that program i need to compare multiple variables together to check whether they are equal or not...
I have provided a snippet of code, what i have tried, whether every su[][] has different value or not. I'm not getting expecting result...
I want to make sure that all the values in su[][] are unequal.
How can i achieve the same, what are mistakes in my snippet?
Thanks...
for(int i=0 ; i<9 ;++i){ //for checking a entire row
if(!(su[i][0]!=su[i][1]!=su[i][2]!=su[i][3]!=su[i][4]!=su[i][5]!=su[i][6]!=su[i][7]!=su[i][8])){
system("cls");
cout<<"SUDOKU'S SOLUTION IS INCORRECT!!";
exit(0);
}
}
To check for each column uniqueness like that you would have to compare each element to the other ones in a column.
e.g.:
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
for (int k = j + 1; k < 9; ++k) {
if (su[i][j] == su[i][k]) {
system("cls");
cout << "SUDOKU'S SOLUTION IS INCORRECT!!\n";
exit(0);
}
}
}
}
Since there are only 8 elements per row this cubic solution shouldn't give you much overhead.
If you had a higher number N of elements you could initialize an array of size N with 0 and transverse the column. For the i-th element in the column you add 1 to that elements position in the array. Then transverse the array. If there's a position whose value is different from 1, it means you have a duplicated value in the column.
e.g.:
for (int i = 0; i < N; ++i) {
int arr[N] = {0};
for (int j = 0; j < N; ++j)
++arr[su[i][j] - 1];
for (int i = 0; i < N; ++i) {
if (arr[i] != 1) {
system("cls");
cout << "SUDOKU'S SOLUTION IS INCORRECT!!\n";
exit(0);
}
}
}
This approach is way more faster than the first one for high values of N.
The codes above check the uniqueness for each column, you would still have to check for each row.
PS: I have not tested the codes, it may have a bug, but hope you get the idea.

Sum up distances in a for loop

I have a vector of Points and I calculate the distances between every Point (P1P2, P1P3, P1P4,....P1PN, P2P1, ... ,PMPN).
Now I want to sum all the distances of Point 1 to every other point, then all the distances of Point 2 to every other point and so on (P1P2+P1P3+...+P1PN, P2P1+P2P2+...+P2PN) an put these distances into a vector. I am stuck in my for loop now:
Here is my code:
// Calculate mass centers
vector<Point2f> centroids_1;
// Calculate distances between all mass centers
vector<double> distance_vector;
for (int i = 0, iend = centroids_1.size(); i < iend; i++) {
for (int j = 0, jend = centroids_1.size(); j < jend; j++) {
double distance = norm(centroids_1[i] - centroids_1[j]);
distance_vector.push_back(distance);
// Here I tried many things with for loops and while loops but
// I couldn't find a proper solution
}
}
Use the standard library instead of raw loops. It will be easier to read and maintain. Plus, the indices are noise. They aren't required for iteration.
for(auto const& point : centroids_1)
distance_vector.push_back(std::accumulate(begin(centroids_1), end(centroids_1), 0.0,
[&](auto res, auto const& point2) { return res + norm(point - point2); }
));
Specifically, we used a range-based-for loop along with std::accumulate. This is the description of what you want to do. Store for each point the accumulated sum of distances between it and other points.
You are not adding distance anywhere.After the first iteration of the inner loop, the answer for first point would be ready which you can save.
Also you don't need to find the difference between same points so skip when i=j
for (int i = 0, iend = centroids_1.size(); i < iend; i++)
{
double distance=0.0;
for (int j = 0, jend = centroids_1.size(); j < jend; j++)
{
if(i==j)
continue;
distance+ = norm(centroids_1[i] - centroids_1[j]);
}
distance_vector.push_back(distance);
}
}

Is there any way I can make this coordinate comparisson function more efficient?

The following function takes three word objects and checks each word's letter coordinates (in a table) against each other. The idea is to get combinations of three words from a list that don't have intersecting letter coordinates. However when you have over 600000 possible combinations this becomes very time consuming.
bool lettersIntersect(word one, word two, word three)
{
for(int i = 0; i < one.getLength(); i++)
for(int j = 0; j < two.getLength(); j++)
if(one.getLetterPosition(i).x == two.getLetterPosition(j).x && one.getLetterPosition(i).y == two.getLetterPosition(j).y)
return true;
for(int i = 0; i < two.getLength(); i++)
for(int j = 0; j < three.getLength(); j++)
if(two.getLetterPosition(i).x == three.getLetterPosition(j).x && two.getLetterPosition(i).y == three.getLetterPosition(j).y)
return true;
for(int i = 0; i < three.getLength(); i++)
for(int j = 0; j < one.getLength(); j++)
if(three.getLetterPosition(i).x == one.getLetterPosition(j).x && three.getLetterPosition(i).y == one.getLetterPosition(j).y)
return true;
return false;
}
Is there a more efficient way of doing this?
I can just give you 1 hint which striked me instantly. Don't blame me if its misleading. You can just try once at your end and see the performance.
Create map (use stl) for each word objects i.e. map_one, map_two, and map_three
Add co-ordinate value as key for each letter of a given word object to its respective map.
Then check using these maps whether there is an intersection.
Check if map in C++ contains all the keys from another map
The only thing I see possible to optimize is avoiding double checks:
for(int i = 0; i < one.getLength(); i++)
for(int j = i+1; j < two.getLength(); j++)
if(one.getLetterPosition(i).x == two.getLetterPosition(j).x && one.getLetterPosition(i).y == two.getLetterPosition(j).y)
return true;
The second for loop was changed from j = 0, to j = i+1, which makes you do the checks in half the time.
Checking between two coordinates points is a n^2 (n-square) problem, which means that the time required to do the checks is proportional to square the number of elements you can check. I thikn there's no other way to optimize this other than avoiding double checks, like I explained.
Of course, in addition to passing by references, like was suggested to you already.
On this homework problem or other learning exercise, you are intended to use a method you have been taught previously that rearranges data to make searching faster. Having rearranged the data, you should be able to find a way to scan it efficiently to find duplicates.

Getting wrong results with OpenMP

I wrote a programm that multiplies a vector by a matrix. The matrix has periodically repeated cells, so I use a temporary variable to sum vector elements before multiplication. The period is the same for adjacent rows. I create a separate temp variable for each thread. sizeof(InnerVector) == 400 and I don't want to allocate memory for it on every iterration (= 600 times).
Code looks something like this:
tempsSize = omp_get_max_threads();
InnerVector temps = new InnerVector[tempsSize];
for(int k = 0; k < tempsSize; k++)
InnerVector_init(temps[k]);
for(int jmin = 1, jmax = 2; jmax < matrixSize/2; jmin *= 2, jmax *= 2)
{
int period = getPeriod(jmax);
#pragma omp parallel
{
int threadNum = omp_get_thread_num();
// printf("\n threadNum = %i", threadNum);
#pragma omp for
for(int j = jmin; j < jmax; j++)
{
InnerVector_reset(temps[threadNum]);
for(int i = jmin; i < jmax; i++)
{
InnerMatrix cell = getCell(i, j);
if(temps[threadNum].IsZero)
for(int k = j; k < matrixSize; k += period)
InnerVector_add(temps[threadNum], temps[threadNum], v[k]);
InnerVector_add_mul(v_res[i], cell, temps[threadNum]);
}
}
}
}
The code looks to be correct but I get wrong result. In fact, I get different results for different runs... sometimes result is correct.
When I compile in debug mode the result is always correct.
When I uncomment the row with "printf" the result is always correct.
p.s. I use Visual Studio 2010.
I suspect there might be a data race in
InnerVector_add_mul(v_res[i], cell, temps[threadNum]);
Since v_res appears to be a resulting vector, and i changes from jmin to jmax in each iteration of the parallelized loop, it can happen that multiple threads write to v_res[i] for the same value of i, with unpredictable result.