C++ Array Sum Values Around Coordinate - c++

I'm having some difficulty summing the values of a multidimensional array around the coordinates given below. Something is wrong with my logic with the index location. Any ideas would be very helpful and if more information is needed, please don't hesitate to ask me.
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
srand(time(0));
int displayArray[11][11];
cout<<"\t\t\t\t\t\t\t\t\t\t\t\t\tColumn\n\n";
for(int column=1;column<10;column++)
{
cout<<"\t "<<column;
}
cout<<"\n\n";
//fill array with random numbers
for(int i=0;i<9;i++)
{
for(int m=0;m<9;m++)
{
displayArray[i][m]=rand()%10;
}
}
cout<<"\n\n\n";
//main data printout
for(int k=0;k<9;k++)
{
cout<<"Row "<<k+1<<"\t ";
for(int l=0;l<9;l++)
{
cout<<displayArray[k][l]<<"\t";
}
cout<<endl<<endl;
}
cout<<"\n\n";
int row=0, column=0;
cout<<"What array cell would you like to see? (Press enter after each entry)\n";
cout<<"Row = ";
cin>>row;
cout<<"Column = ";
cin>>column;
cout<<"\nThe number "<<displayArray[row-1][column-1]<<" is in cell "<<row<<","<<column;
int coord1=displayArray[row-2][column+2],
coord2=displayArray[row+2][column+2],
coord3=displayArray[row-2][column-2],
coord4=displayArray[row-2][column+2],
coord5=displayArray[row-2][column+2],
coord6=displayArray[row-2][column+2],
coord7=displayArray[row-2][column+2],
coord8=displayArray[row-2][column+2];
int sum=coord1+coord2+coord3+coord4+coord5+coord6+coord7+coord8;
cout<<"\n\nThe sum of the cells surrounding "<<row<<","<<column<<" is "<<sum;
cin.get();
cin.get();
return 0;
}

Your problem may be that you are using row/column -2 and row/column +2 as your adjacent directions, which is not correct. If (row-1, col-1) is your current cell, than you want row/col -2 and row/col +0.
int coord1=displayArray[row-2][column-2],
coord2=displayArray[row-2][column-1],
coord3=displayArray[row-2][column],
coord4=displayArray[row-1][column-2],
coord5=displayArray[row-1][column],
coord6=displayArray[row][column-2],
coord7=displayArray[row][column-1],
coord8=displayArray[row][column];
int sum=coord1+coord2+coord3+coord4+coord5+coord6+coord7+coord8;
This can be done much more programmatically, however:
int sum = 0;
for (int x=row-2; x<=row; x++) {
for (int y=column-2; y<=column; y++) {
if ((x != row-1) || (y != column-1)) { //Avoids "center" cell (self)
sum += displayArray[x][y]
}
}
}

So if I'm understanding this correctly, the user inputs a row and column number, which corresponds to the value located in displayArray[row-1][column-1]
Thus, the coordinates around that cell should be.
displayArray[row][column]
displayArray[row-1][column]
displayArray[row-2][column]
displayArray[row][column-1]
displayArray[row-2][column-1]
displayArray[row][column-2]
displayArray[row-1][column-2]
displayArray[row-2][column-2]
I'm not sure exactly why you're using the coordinates you are, but that is your problem.
Also, you're going to want to make sure your program doesn't crash if the user selects a cell on the border of the array. eg: If you try to search coordinates around the cell (0,0), the program will crash when trying to load a value for displayArray[-1][-1]

Your mistake is in translating 0 based to 1 based indexing. The arrays are 0 based. You're having them enter in a 1 based row. Then you want to add the 8 numbers around it. If they entered 0 based numbers and entered N, you'd want to sum [n-1], n, and n+1 for each row/column. To deal with 0 based, you want to do n-2, n-1, and n. But you're doing n-2 and n+2. You're also not calculating the middle of the rows anywhere near right.
Best practice is not even to do the math like that. It would be to read in the row/column number, then immediately subtract 1 to make it 0 based, and deal with it as 0 based from then on.

Related

Logic error: Incorrect computation of mean centroid ,Infinite Execution of , 'entries ' function - K means clustering for a set of points, in C++

I am writing a program for K-means clustering, to find the clusters that each point should belong to. There are 8 points and 3 clusters for this code. Somehow in my code the 'entries' function is executing infinitely. I couldn't find where I have gone wrong. This is the logic that I'm following:
Hard coded input of the 8 points
Randomly generate 3 cluster centers
Calculate distance of each point from the 3 cluster centers and use arr1[][] to store the distances.
In cent_tally[][], store the number of the cluster that each point should belong to. eg. 0 for cluster 1, 1 for cluster 2 and 2 for cluster 3. (Also storing the same values in the 4th column of the 2-D array, 'arr1').
Calculate the mean centroids (cluster centers) by using the clusters nos. for each point.
Again call the 'entries' function to calculate the distances and the cluster no. to which each point should belong, but this time using the 2nd set of centroids.i.e. the mean centroids.
If the second set of cluster nos. for each point, (stored in the 2nd column of cent_tally[][]), tallies with the cluster nos. for each point using the randomly generated centroids(first column of cent_tally[][]), then print cent_tally[][], print arr1[][] and stop.
Here is the code:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
using namespace std;
class points
{
float x;
float y;
static int point_cnt;
static int flag;
int cent_tally[8][4];
int count2;
struct centroids
{
float cx;
float cy;
}c[3];
public:
points()
{
count2=0;
for(int i=0;i<3;i++)
{
c[i].cx=0;
c[i].cy=0;
}
for(int i=0;i<8;i++)
{
for(int j=0;j<4;j++)
{
cent_tally[i][j]=0;
}
}
}
void means(points * );
float dist(float a,float b,float c,float d);
int entries(float c11x,float c11y,float c22x,float c22y,float c33x,float c33y,float arr[8][4],points *p);
};
int points::point_cnt=8;
int points::flag=0;
int points::entries(float c11x,float c11y,float c22x,float c22y,float c33x,float c33y,float arr[8][4],points *p)
{
float sum1x,sum1y,sum2x,sum2y,sum3x,sum3y; //to calC mean centroids
sum1x=0;
sum1y=0;
sum2x=0;
sum2y=0;
sum3x=0;
sum3y=0;
int cnt1,cnt2,cnt3;
cnt1=0;
cnt2=0;
cnt3=0; //to calC mean centroids
//count2=0;
//in the first iteration of entries, count2=0
cout<<"count 2 value:"<<count2<<endl;
for(int k=0;k<8;k++) //0 to 7 for 8 points
{
arr[k][0]=dist(p[k].x,p[k].y,c11x,c11y);
arr[k][1]=dist(p[k].x,p[k].y,c22x,c22y);
arr[k][2]=dist(p[k].x,p[k].y,c33x,c33y);
float temp,min;
temp = (arr[k][0] < arr[k][1]) ? arr[k][0] : arr[k][1];
min = (arr[k][2] < temp) ? arr[k][2] : temp;
//cout<<"mins:"<<min<<endl;
for(int l=0;l<3;l++)
{
if(arr[k][l]==min)
{
arr[k][3]=l; //0 for c1, 1 for c2, 2 for c3 in 4th column of table
cent_tally[k][count2]=l;
if(l==0)
{
sum1x+=p[k].x;
sum1y+=p[k].y;
cnt1++;
}
else if (l==1)
{
sum2x+=p[k].x;
sum2y+=p[k].y;
cnt2++;
}
else if (l==2)
{ sum3x+=p[k].x;
sum3y+=p[k].y;
cnt3++;
}
else
{
cout<<"";
}
}
}
}
count2++;//for index into cent_tally
//finding mean centroid ...
//re entering values of mean centroid into the same structure created for 3 centroid coordinates ...
c[0].cx=sum1x/cnt1;
c[0].cy=sum1y/cnt1;
c[1].cx=sum2x/cnt2;
c[1].cy=sum2y/cnt2;
c[2].cx=sum3x/cnt3;
c[2].cy=sum3y/cnt3;
//now the struct contains mean centroids
for(int i=0;i<8;i++)
{ int temp=0;
temp=count2-1;
if(cent_tally[i][temp]==cent_tally[i][count2])
{
flag++;
}
else
{
break;
}
}
if(flag==8)
{
cout<<"centroids found: "<<endl;
for(int i=0;i<8;i++)
{
for(int j=0;j<4;j++)
{
cout<<" "<<cent_tally[i][j];
}
cout<<endl;
}
return 0;
}
else
{
return flag;
}
//while(flag!=8) //WHILE ALL 8 entries of latest 2 columns of cent_tally are not matching
//{
//entries(c[0].cx,c[0].cy,c[1].cx,c[1].cy,c[2].cx,c[2].cy,arr,&p[0]);
//}
}
float points::dist(float a,float b,float c,float d)
{
return (abs(a-c)+abs(b-d));
}
void points:: means(points * p)
{
float arr1[8][4]; //array to store dist b/w each point and cluster center and cluster values for each point after distance calculation
float arr2[8][4];
//let c1 c2 and c3 be initial cluster centers
//float c1x,c2x,c1y,c2y,c3x,c3y;
//Can take input from a file also...
p[0].x=2;
p[0].y=2;
p[1].x=1;
p[1].y=14;
p[2].x=10;
p[2].y=7;
p[3].x=1;
p[3].y=11;
p[4].x=3;
p[4].y=4;
p[5].x=11;
p[5].y=8;
p[6].x=4;
p[6].y=3;
p[7].x=12;
p[7].y=2;
srand ( time(NULL) );
for(int i=0;i<3;i++) //for 3 cluster centers, we need 3 centroids
{
int randIndex=1+rand()%(point_cnt-i-1);//where 8 is the no. of points
c[i].cx=p[randIndex].x;
c[i].cy=p[randIndex].y;
}
int val;
val=entries(c[0].cx,c[0].cy,c[1].cx,c[1].cy,c[2].cx,c[2].cy,arr1,&p[0]);
while(val!=8)
{
val=entries(c[0].cx,c[0].cy,c[1].cx,c[1].cy,c[2].cx,c[2].cy,arr1,&p[0]);
}
for(int i=0;i<8;i++)
{
for(int j=0;j<4;j++)
{
cout<<arr1[i][j]<<" ";
}
cout<<endl;
}
//displaying 1st table
//2.1 calculate mean centroid
//2.2 re enter new values in same table
//2.3 first 2 columns of cent_tally
//2.4 if not same repeat step 2.1
}
int main()
{
int c=8;
points p[8];
points obj;
obj.means(&p[0]);
return 0;
}
Another mistake I made, was not initialising flag=0 at the beginning of the 'entries' function!
Now my entries function is not running infinitely, but I have the following problems now:
Mean centroid(Second set of centroids onwards) is computed wrong after the first set of centroids are used
I'm trying to copy the fourth column of arr[][]into the first column and next columns eventually, of cent_tally[][] by using count2 as index , but the first column of cent-tally does not match the 4th column of arr[][]
I'm unable to figure where I have gone wrong.
Due to this logic in entries function
if(flag==8)
{
cout<<"centroids found: "<<endl;
for(int i=0;i<8;i++)
{
for(int j=0;j<4;j++)
{
cout<<" "<<cent_tally[i][j];
}
cout<<endl;
}
return 0;
}
else
{
return flag;
}
8 will never be returned from entries function.
On the other hand, this logic in means function
while(val!=8)
{
val=entries(c[0].cx,c[0].cy,c[1].cx,c[1].cy,c[2].cx,c[2].cy,arr1,&p[0]);
}
loops until 8 is returned from the entries function.
This seems to be the cause of the infinite loop. Consider adjusting the behavior of one of these two point.
Reasons for incorrect mean centroid computation:
Most Important: Inside the for loop where l runs from 0 to 2, if two values of distances are the same, the counts get incremented for two values of l, hence a flag can be used to ensure that only one minimum distance is taken into consideration, for deciding the centroid to which the point belongs to.
Abs takes integer values and hear we are dealing with float, so we need to define a function which handles float values .
Flag should be initialised to 0 in the beginning of 'entries' function.
If two randomly generated centroids are the same, you may not get the right answer.

Getting Stuck On the Algorithm for q bishops on an n*n chessboard

I'm using C++, but my question is more about algorithms than implementation.
The problem is the following:
Write a program that inputs two integers n and k, where n>=k. Your program should calculate the number of different ways that k bishops could be placed on an nXn chessboard.
My basic idea is to represent each bishop as a struct with an X value and a Y value. Then I place the bishops on the board to get a configuration.
I have written a method called moveToNextPlace that allows me to move a bishop into the next available spot. I return a string to help with debugging.
struct bishop {
int y=0;
int x=0;
string moveToNextPlace (int n){
if (y<n-1) {y++; return "move to next y value";}
else if (x<n-1) {x++; return "move to next x value";}
else {reset(); return "reset";};
}
void setValuesLike (bishop b){
y=b.y;
x=b.x;
}
void reset (){
y=0;
x=0;
}
bool clashesWith (bishop b){
if (b.x==x && b.y==y){
return true;
}
if ( b.y-y == b.x-x ) return true; //if their slope is 1
return false;
}
};
I then set the board to an initial configuration by calling findSolutions with my desired settings.
int findSolutions (int k, int n){ //k bishops on n*n board
bishop *b = new bishop [k];
for (int i=0; i<k; i++){
findAspot (b, n, i);
}
}
bool check (int num, bishop b[]){
for (int i=0 ; i<num; i++){
if (b[i].clashesWith (b[num])) return false;
}
return true;
}
void findAspot (bishop b[], int n, int num){ //n=boardsize
while (1){
if (check(num, b)){return;}
if (b[num].moveToNextPlace(n) == "reset") break;
}
b[num-1].moveToNextPlace(n);
findAspot (b, n, num-1);
b[num].setValuesLike ( b[num-1] );
findAspot (b, n, num);
}
I then want to keep backtracking until I have a total number of solutions, but I get stuck on how to find the next solution.
I thought I could write a findNextSolution that keeps getting called at the end of the findSolutions function until it reaches a cycle. But I don't know what algorithm to use to find the next solution.
You're off to a good start with your idea of storing the bishop positions in an array. This is a compact representation of a board state.
You'll have to correct your method of checking whether one bishop clashes with another. Bear in mind that two clashing bishops may be separated by a vertical distance dy and a horizontal distance dx such that dx == -dy. Therefore, you will want to compare the absolute values: the bishops clash if abs(dx) == abs(dy).
Now on to the general problem of counting the number of board states in which k bishops are arranged without clashing. You'll want to define a function that returns an integer value. Let's say that this function looks like
count(currentBishops, numRemaining)
where currentBishops is a feasible placement of bishops and numRemaining is the number of bishops you haven't placed yet.
Then the solution to the problem is
count([], k)
where [] means that no bishops have been placed yet.
The count function can be implemented according to the following pseudocode.
count(currentBishops, numRemaining):
if numRemaining == 0:
return 1
sum = 0
for each possible board position (x, y):
if (x, y) does not clash with any bishop in currentBishops:
let nextBishops be currentBishops augmented with (x, y)
sum += count(nextBishops, numRemaining-1)
return sum
In order to avoid an exponential explosion of recursive calls, you'll want to cache the result of each subproblem. This technique is called memoization, and you can implement it as follows.
let memo be a map from (currentBishops, numRemaining) to an integer value
count(currentBishops, numRemaining):
if numRemaining == 0:
return 1
if memo contains (currentBishops, numRemaining):
return memo[(currentBishops, numRemaining)]
sum = 0
for each possible board position (x, y):
if (x, y) does not clash with any bishop in currentBishops:
let nextBishops be currentBishops augmented with (x, y)
sum += count(nextBishops, numRemaining-1)
memo[(currentBishops, numRemaining)] = sum
return sum
The mapping of currentBishops should be one that doesn't care about the order in which you have placed the bishops. You can accomplish this by sorting the bishop positions or making a bitmap of the board when you compute the key for memo.

calculating the distance between 2 points openCV c++

Basically i have to figure out whether the label on on object is straight. I have an edge image of the object. I would like to calculate the distance between the 2 edges on either side in a single row.
My algorithm involves iterating through a row until a white pixel is found. Then calculating the number of black pixels until the next white is found. However when i run the code the answer is always zero.
Code:
for(int i = 0; i < img.cols; i++)
{
int num = nms_result.at<int>(i,100);
//cout <<num<<endl;
if(num > 0) {
stage2 = true;
}
if (stage2 ==true)
counter4++;
{
int num2 = nms_result.at<int>(i,100);
;
if ((num2 < 1) && (counter4 >=1 )) {
counter2++;
}
else counter4 = 0;
}
}
I have tried a lot of things but none seem to work.
Problem number 1: If I'm reading your code right, 'num' and 'num2' are always the same, since they're in the same loop.
Problem number 2: What's the output here? a little hard to tell with your formatting. Consider using some indentations with your nested ifs.

3D Array to 3D std::vector

I replaced a 3D array with a 3D std::vector in my code function and it's entering a infinite loop .Could you give me a hint,I really need to use a vector instead an array.Thanks:)
My initial code was:
//arr is a 3D array of a sudoku table,the 3 rd dimension is for keeping values 0 to 13
//for a cell, and when I assign values I start from index 1 to 12
bool sol(int arr[12][12][13]) {
int row,col;
if(!find_empty(arr,row,col)) return true;
for(int i=1;i< 12;i++) { //for digits 1 to 12
if(is_working(arr,row,col,arr[row][col][i]) ) { //if i can put the value in a cell
arr[row][col][0] = arr[row][col][i]; //replace the first element for a cell with that value
//here I want to use vector because I want to use an ac3 algorithm
//and remove those values that not satisfy constraints and shrink domain size having less values to verify with backtrack
if(sol(arr)) return true;
arr[row][col][0] = 0;
}
}
return false;//if not backtrack
}
I replace arr with:
std::vector<std::vector<std::vector<int> > > vec;
vec.resize(12);
for(int i=0;i<12;i++)
{
vec[i].resize(12);
for(int j=0;j<12;j++)
{
vec[i][j].resize(13);
for(int k=0;k<13;k++)
vec[i][j][k]=table[i][j][k];
}
}
bool sol(std::vector<std::vector<std::vector<int> > >& vec) {
int row,col;
if(!find_empty(vec,row,col)) return true;
for(int i=1;i< vec[row][col].size();i++) {//for remainig values in domain
if(is_working(vec,row,col,vec[row][col][i]) ) {//same as above but having less values to verify for
vec[row][col][0] = vec[row][col][i];
if(sol(vec)) return true;
vec[row][col][0] = 0;
}
}
return false;
}
and now it's entering a infinite loop!The initial code has no errors,it's a simple backtracking.The problem appears after I replace arr with vec.Could you give me some advice on how to replace 3D arr with an 3D vector
Your question is not clear enough. If you can also post the code for is_working and find_empty, then we would be able to see how you are getting the values of row and column.
I would have put this as a comment but being a new member and not having enough reputations, I have to put this as an answer. I'll edit it once you share the code for is_working() and find_empty()
I have solved the problem. I used a matrix of vectors instead a 3D vector and it works great :D
maybe this better for 3d one, 4x4x4
std::vector<std::vector<std::vector<double>>> matrix;
matrix.resize(4, std::vector<std::vector<double>>(4,std::vector<double(4)));

Maximum matching in a graph

I have an interesting problem:
My program must to find the maximum number of 1.
But that's not all!.
If the program has "seen" 1, then it should clear the entire column and row in which the 1 is located.
The problem I have:
I can not find the maximum number of 1, I do not know how to do that.
For you I made a small example, I hope it will be clear to you. The program must work like this:
There is a matrix:
1 0 0 0
1 0 1 1
1 1 1 1
1 0 0 1
The program found 1 (position [0][0] I've highlighted it in black), and cleared the row and column:
After this we find the next 1, cleared the row and columnand so on:
At the end, the program should print the number of black cells.
In my example it's 4
How to do it in C++ code? Please help me! Thank you.
I prefer to do it like this (see code below): Use two "for" loops and inside the second use conditional "if" to add the third "for" loop to set to 0.
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
if(cow[j][i]==1)
{
cnt++;
for(int k=0;k<n;k++)
cow[k][i]=cow[j][k]=0;
break;
}
}
it's not clear how you search for the 'next' 1 in your matrix and if the matrix can only contain 0 and 1. But if there is a clear definition of what 'next' is, then you just code exactly as you have described it above. A possible code snippet looks like this (not tested, not even compiled):
bool find_next_one(int&x, int&y, matrix const&M)
{
// next is in (col,row) order
for(; x!=M.size(0); ++x)
for(; y!=M.size(1); ++y)
if(M(x,y)==1) return 1;
return 0;
}
int count_one(matrix const&M_original)
{
matrix M(M_original); // make copy where we can set elements to 0
int count=0;
int x=0,y=0;
while(find_next_one(x,y,M)) {
++count;
for(int i=0; i!=M.size(1); ++i) M(x,i) = 0;
for(int i=0; i!=M.size(0); ++i) M(i,y) = 0;
}
return count;
}
Noticed this looks like a matrix singularity type check - especially if 1s and 0s are the only thing to be used.
You can check the determinate of the matrix. Non zero means it is equal to the number of rows and columns (if the matrix is always square.) If det(0), then use any technique you want to bring the matrix down to reduced form to see how many 0'd columns you have - or just do the reduction first and walk down the diagonal counting.
Heck sorting the columns by their added value, will put it in diagonal form for you. That would make it pretty easy also to check for 0 columns.
I won't write all the code for you, but will suggest some things to get you on track. You should understand how to iterate over a two dimensional array (the matrix) and also how to iterate over a single row or column within that matrix.
Given a (hard coded) definition of matrix that looks like this:
struct Matrix4x4
{
int m[4][4];
};
To iterate over all elements you want to write something like this:
Matrix4x4 matrix;
for (size_t row = 0; row < 4; ++row)
{
for (size_t col = 0; col < 4; ++col)
{
// do something with 'matrix.m[row][col]'
}
}
This will iterate over your matrix from top left (0,0) to bottom right (3,3). I am assuming that this is the traversal order you have been told to use.
To process a row you want to write something like this:
void FunctionThatOperatesOnARow(Matrix4x4& matrix, size_t row)
{
for (size_t col = 0; col < 4; ++col)
{
// do something with 'matrix.m[row][col]'
}
}
To process a column you want to write something like this:
void FunctionThatOperatesOnAColumn(Matrix4x4& matrix, size_t col)
{
for (size_t row = 0; row < 4; ++row)
{
// do something with 'matrix.m[row][col]'
}
}
What you need to do now is modify the first bit of code that iterates over all elements and get it to check for a 1. You then need to call the appropriate functions to clear the current column and row (which you can base on the latter two examples).
For the final result you can simply increment a local counter variable each time you detect a 1.