Index of the Closest point in an array each containing 3 elements - c++

I am trying to find the index of the closest point in an array(pts) containing 3 elements each.
I have written the following code, but it does not return me the index of the closest points:- Would appreciate if anyone could please let me know where i. am wrong. Thanks!
void point_index(Point pts[], int &size)
}
cout << x << " " << y << endl;
Thank you, everyone, for the help! I have figured out my mistake and corrected the code!

You are not storing the minimum value in min, after compare store the minimum value in min and set distance value outside if to compare properly.
a = get_distance(pts[i],pts[j]);
if (a < min) {
x = i;
y = j;
min = a;
}

Once you find the minimum, you need to assign x,y and min.
Try this code:
double a;
int x = 0, y = 1;
double min = get_distance(pts[x],pts[y]);
for (int i = 0; i < size; i++)
{
for (int j = i+1; j < size; j++)
{
double d = get_distance(pts[i], pts[j]);
if (d < min)
{
x = i;
y = j;
min = d;
}
}
}
cout << x << " " << y << endl;

Related

Array elements changing values if I comment out cout statement. Is this memory leak related?

I'm working on a KNN algorithm with 2D arrays. It worked great when I first had the nodes be simple X and Y coordinates, but when I changed it to 2D arrays and reworked some things, I run into a funny issue.
#include <iostream>
#include <math.h>
using namespace std;
//A node
struct Node
{
int groupValue;
int col = 16; //We only have to update these to reflect the bitmap dimensions
int row = 16;
int bitmap[16][16];
float distance = -1;
//distance is the distance this node is from another
//Overloading this operator to make swapping them with insertion sort easier
Node& operator =(const Node& n)
{
for(int a = 0; a < row; a++)
{
for(int b = 0; b < col; b++)
{
bitmap[a][b] = n.bitmap[a][b];
}
}
distance = n.distance;
groupValue = n.groupValue;
return *this;
}
};
void printNode(Node n)
{
for(int a = 0; a < 16; a++)
{
for(int b = 0; b < 16; b++)
cout << n.bitmap[a][b] << ".";
cout << endl;
}
}
struct Group
{
int frequency = 0;
int id;
};
void insertionSort(Node arr[], int n)
{
int i, key, j;
for (i = 1; i < n; i++)
{
key = arr[i].distance;
j = i - 1;
while (j >= 0 && arr[j].distance > key)
{
Node temp = arr[j+1];
arr[j + 1] = arr[j];
arr[j] = temp;
j = j - 1;
}
arr[j + 1].distance = key;
}
}
//Takes two bitmaps and find the distance between each pixel
//using the formula d=sqrt(sum((pixel_1-pixel_2)^2))
float bitmapDistance(Node n1, Node n2)
{
Node differences; //Node's bitmap data will be the differences
//squared of each pixel from n1 and n2.
float diff;
for(int a = 0; a < n1.row; a++)
{
for(int b = 0; b < n1.col; b++)
{
diff = n1.bitmap[a][b] - n2.bitmap[a][b];
differences.bitmap[a][b] = diff * diff; //Squared difference
}
}
//Now we need to sum up the squared differences that we stored earlier
float sum;
for(int a = 0; a < n1.row; a++)
{
for(int b = 0; b < n1.col; b++)
{
sum += differences.bitmap[a][b];
}
}
//Now just take the square root of the sum and return it
if(sum < 0.01) //To fix some weird rounding issues I added this. 0.01 is arbitrary.
return 0;
return sqrt(sum);
}
/*
*Classify the node using KNN algorithm
*Multiple groups can be used, and we count how many neighbors
*belong to each group.
*n is the total amount of nodes
*k is the number of nearby neighbors
*/
int classify(Node arr[], int n, int k, Node node)
{
//Two switches for sampling, recorded as binary (0-3)
Group g0;
g0.id = 0;
Group g1;
g1.id = 1;
Group g2;
g2.id = 2;
Group g3;
g3.id = 3;
Group groupFrequency[4] = {g0, g1, g2, g3};
//For each neighbor of the given node (node) we use the distance formula
//and set it's distance member variable to this measurement
for(int a = 0; a < n; a++)
{
arr[a].distance = bitmapDistance(node, arr[a]);
//cout << arr[a].distance << ","; //<===============PROBLEM AREA===============
}
cout << endl << "----------" << endl;
insertionSort(arr, n-1);
for(int a = 0; a < n; a++)
cout << arr[a].distance << ",";
cout << endl << "----------" << endl;
//Look at all the nearest neighbors and see which group they belong to
//Increase a counter for each group the neighbor belongs to
for(int i = 0; i < k; i++)
{
if(arr[i].groupValue == 0)
groupFrequency[0].frequency++;
else if(arr[i].groupValue == 1)
groupFrequency[1].frequency++;
else if(arr[i].groupValue == 2)
groupFrequency[2].frequency++;
else if(arr[i].groupValue == 3)
groupFrequency[3].frequency++;
}
cout << "Neighboring group frequencies:" << endl;
cout << "Group Zero: " << groupFrequency[0].frequency << endl;
cout << "Group One: " << groupFrequency[1].frequency << endl;
cout << "Group Two: " << groupFrequency[2].frequency << endl;
cout << "Group Three: " << groupFrequency[3].frequency << endl;
cout << "-------------------------------------------------" << endl;
//Now we just need to look at the most common frequency and classify our node
int highestFrequency = 0;
int groupNumber = -1; //If -1 is returned, something went wrong.
for(int a = 0; a < 4; a++)
{
if(groupFrequency[a].frequency >= highestFrequency)
{
highestFrequency = groupFrequency[a].frequency;
groupNumber = groupFrequency[a].id;
}
}
return groupNumber;
}
//This stuff is just setup for testing purposes. Could this be the issue's origin?
int main()
{
Node nodeArray[200];
for(int c = 0; c < 100; c++)
{
for(int a = 0; a < 16; a++)
{
for(int b = 0; b < 16; b++)
{
nodeArray[c].groupValue = 0;
nodeArray[c].bitmap[a][b] = rand()%10;
}
}
}
for(int c = 100; c < 200; c++)
{
for(int a = 0; a < 16; a++)
{
for(int b = 0; b < 16; b++)
{
nodeArray[c].groupValue = 1;
nodeArray[c].bitmap[a][b] = 50;//rand()%10+50;
}
}
}
Node testNode;
for(int a = 0; a < 16; a++)
{
for(int b = 0; b < 16; b++)
{
testNode.bitmap[a][b] = 50;//rand()%10+50;
}
}
int num = classify(nodeArray, 200, 189, testNode);
cout << "Test node has a group classification of: " << num << endl << endl;
printNode(testNode);
cout << endl << "last node in array:" << endl;
printNode(nodeArray[199]);
cout << endl << bitmapDistance(testNode, nodeArray[199]) << endl << "first node in array:" << endl;
printNode(nodeArray[0]);
cout << bitmapDistance(testNode, nodeArray[0]);
}
The problem specifically is on line 124, in the classify() function in the for loop
for(int a = 0; a < n; a++)
{
arr[a].distance = bitmapDistance(node, arr[a]);
//cout << arr[a].distance << ","; //<====PROBLEM AREA
}
This loop is responsible for calculating the distance each node is from the sample/test node. The "arr" array is then sorted a couple of lines later via insertion sort.
If I have the for loop print out the distance values, everything works perfectly fine. I can see that all the data is properly there.
However, if I comment it out, and only print the sorted data, everything is wrong (the data does not mess up if I comment out the print statements for the sorted data, strangely enough. It's just this one line that breaks everything).
I have attached images depicting the differences between the commented line (wrong) and the uncommented line (correct) running to better show what issues I'm dealing with.
Basically, the data will lose decimal precision, have seemingly random values, and any zero value will be non-existent if I comment out this specific line.
(I know the K value should be low, but I'm using high numbers for testing right now)
Some of the output when I don't comment out the line
Some of the output when I do comment out the line
As you can see, when I comment out the line, all the sorted distance values become garbage.
What can I do to fix this?

Array Sum with Pointers i have a problem in the sum

I have this code. and I have a problem with it. When I run it for these numbers "1,1,1,1,1" it answers me right but when I use these numbers "2,1,3,2,2" or any other numbers it answers me wrong. What is the problem?
#include <iostream>
using namespace std;
int main() {
int size = 5;
int array1[size];
int i, j, *p;
int sum = 0;
p = &array1[j];
for (int i = 0; i < size; i++) {
cout << "give next number";
cin >> array1[i];
cout << "\n";
}
cout << "the array is:"
<< "\n";
for (int j = 0; j < size; j++) {
cout << array1[j] << "\n";
sum = sum + *p;
}
cout << "the sum of array elements is: " << sum;
return 0;
}
So you have one problem
p = &array1[j];
What you are doing is taking the address of jth element of an array. In you case j is uninitialized which leads to UB since j might contain any variable.
To fix this you can initialize j to 0 (j = 0). Or to just get an address of first element in array you can do following:
p = array;
Than comes your loop, which is summit value at address of arr[j] which is UB as I stated above.
cout << "the array is:" << "\n";
for (j = 0; j < size; j++) {
cout << array1[j] << "\n";
sum = sum + *(p + j);
}
Your problem here was that you were adding array1[0] all the time. (That is if you initialized j to 0).
Other things to note is that you are re declaring i and j
int i, j, *p;
...
for (int i = 0; ...)
...
for (int j = 0; ...)
You could do just
for (i = 0; ...)
...
for (j = 0; ...)
to set already declared variables to 0.
Here is entire program:
#include <iostream>
int main() {
int size = 5;
int array1[size];
int i, j, *p;
int sum = 0;
// p = &array1[j]; // UB j not initialized but used
/* solution 1
j = 0;
p = &array1[j]
*/
// solution 2 which is same as solution 1
p = array1; // gets address of array[0]
for (i = 0; i < size; i++) { // no need for `int` in front of i
// i is already declared above
// my preference is to declare i here
// and remove declaration above
std::cout << "give next number";
std::cin >> array1[i];
std::cout << "\n";
}
std::cout << "the array is:"
<< "\n";
for (j = 0; j < size; j++) { // same as above
std::cout << array1[j] << "\n";
sum = sum + *(p + j);
}
std::cout << "the sum of array elements is: " << sum;
return 0;
}
input:
give next number5
give next number4
give next number3
give next number2
give next number1
output
the array is:
5
4
3
2
1
the sum of array elements is: 15

How to print diamond shape w/ c++

I need help, I created a short little program a while ago where it would print a simple pyramid with "*" like this:
*
***
*****
but I decided to challenge myself and see if I could create a simple diamond shape like this:
*
***
*****
***
*
Here is my code so far.
I should also add that the value you input, for example 5, determines how big the diamond is.
#include <iostream>
#include <sstream>
using namespace std;
int main() {
int value = 0;
cout << "Please enter in a value: ";
cin >> value;
cout << endl;
for (int i = 0; i < value; i++) {
//print spaces v v v
for (int x = 0; x < (value - i - 1); x++) {
cout << " ";
}
//print * v v v
for (int y = 0; y < (2 * i + 1); y++) {
cout << "*";
}
cout << endl;
}
for (int i = 0; i < value; i++) {
int number = 0;
number+= 2;
//print spaces v v v
for (int x = 0; x < (value - value + i + 1); x++) {
cout << " ";
}
//print * v v v
for (int y = 0; y < (/*ATTENTION: What do I do here? Plz help*/); y++) {
cout << "*";
}
cout << endl;
}
return 0;
}
What I've been trying to do is figure out what to put inside the parenthesis where it says (//ATTENTION). I've been working for at least an hour trying to do random things, and one time it worked when I input 4, but not for 5, and it's just been very hard. This is key to building the diamond, try putting in just value and compile to see what happens. I need it to be symmetrical.
I need to know what to put inside the parenthesis please. I'm sorry this is very long but the help would be appreciated thanks.
I also apologize if my code is messy and hard to read.
int number = 0; and number+= 2;
value - value inside for (int x = 0; x < (value - value + i + 1); x++) {
are not required.
Inside the parenthesis, you can use
2*(value-i-1)-1
However, I would suggest you to first analyze the problem and then try to solve it instead of trying random things. For instance, let's consider the cases of even and odd inputs i.e., 2 and 3.
Even Case (2)
*
***
***
*
The Analysis
Row Index Number of Spaces Number of Stars
0 1 1
1 0 3
2 0 3
3 1 1
For row index < value
Number of Spaces = value - row index - 1
Number of Stars = 2 * row index + 1
For row index >=value
The number of spaces and stars are simply reversed. In the odd cases, the situation is similar too with a small exception.
Odd Case (3)
*
***
*****
***
*
The Analysis
Row Index Number of Spaces Number of Stars
0 2 1
1 1 3
2 0 5
3 1 3
4 2 1
The small exception is that while reversing, we have to ignore the row index = value.
Now, if we put the above analysis in code we get the solution
//Define the Print Function
void PrintDiamond(int rowIndex, int value)
{
//print spaces v v v
for (int x = 0; x < value - rowIndex -1; x++) {
cout << " ";
}
//print * v v v
for (int y = 0; y < 2 * rowIndex + 1; y++) {
cout << "*";
}
cout << endl;
}
And then inside main
//Row index < value
for (int i = 0; i < value; i++) {
PrintDiamond(i,value);
}
//For row index >= value reversing the above case
//value-(value%2)-1 subtracts 1 for even and 2 for odd cases
//ignore the row index = value in odd cases
for (int i = value-(value%2)-1; i >=0; i--) {
PrintDiamond(i,value);
}
#include <iostream>
#include <sstream>
using namespace std;
int main() {
int value = 0;
cout << "Please enter in a value: ";
cin >> value;
cout << endl;
for (int i = 0; i < value; i++) {
//print spaces v v v
for (int x = 0; x < (value - i - 1); x++) {
cout << " ";
}
//print * v v v
for (int y = 0; y < (2 * i + 1); y++) {
cout << "*";
}
cout << endl;
}
for (int i = 0; i < value-1; i++) {
// int number = 0;
// number+= 2;
// //print spaces v v v
for (int x = 0; x < i+1; x++) {
cout << " ";
}
//print * v v v
for (int y = 0; y < (2*(value-1-i)-1); y++) {
cout << "*";
}
cout << endl;
}
return 0;
}
I hope that you will get this .Also in the second for loop you were iterating it one extra time by iterating the loop upto value. But since the pyramid is symmetric so the no of rows in the pyramid will be 2*value-1.So I in the second loop i should vary upto value -1.
This code should resolve the problem:
#include <sstream>
using namespace std;
void printSpaces(int howMany) {
for(int i = 0; i < howMany; i++) cout << " ";
}
void figure(int size) {
bool oddSize = size % 2 == 1;
int center = size / 2;
int spaces = size / 2;
// If figure is of an odd size adjust center
if (oddSize) {
center++;
} else { // Else if figure is of even size adjust spaces
spaces--;
}
for (int i = 1; i <= center; i++) {
printSpaces(spaces);
for(int j = 0; j < 1 + (i - 1) * 2; j++) cout << "*";
cout << endl;
spaces--;
}
spaces = oddSize ? 1 : 0; // If the figure's size is odd number adjust spaces to 1
center -= oddSize ? 1 : 0; // Adjust center if it's an odd size figure
for(int i = center; i >= 1; i--) {
printSpaces(spaces);
for(int j = 0; j < 1 + (i - 1) * 2; j++)
cout << "*";
cout << endl;
spaces++;
}
}
int main() {
int value = 0;
while(value < 3) {
cout << "Please enter in a value (>= 3): ";
cin >> value;
cout << endl;
}
figure(value);
return 0;
}

Selection Sorting Using 2 Arrays

Suppose I want to take an array of pointers that point to x, y, z coordinates such as:
(1, 2, 4)
(2, 3, 8)
(3, 5, 1)
Then I wanted to take each of those values and compare the distance from point (1, 2, 3) and then sort the distance from each point in descending order.
How would I do that? This is the code I have so far. But I dont know how to get the second array to point back to the original values. Any help would be great.
void sortPointsByDistanceFromRefPoint(Points* points, Point* ref_point)
{
double *array;
double x0,y0,z0;
x0 =ref_point->x;
y0 =ref_point->y;
z0 =ref_point->z;
Point** point_array = points-> point_array;
int num_points = points->num_points;
array = new double[num_points];
double distance;
double x,y,z;
for (int i = 0; i< num_points; i++)
{
Point* point = point_array[i];
x = point->x;
y = point ->y;
z = point ->z;
distance = sqrt( pow((x-x0),2) + pow((y- y0),2) + pow((z-z0),2));
array[i] = distance;
}
double tmp;
for( int i = 0; i < num_points; i++)
cout << array[i] << " " << endl;
cout << endl;
cout << endl;
for (int i = 0; i < num_points -1; i++)
for (int j = i+1; j < num_points; j++)
if (array[i] > array[j])
{
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
for( int i = 0; i < num_points; i++)
cout << array[i] << " " << endl;
cout << endl;
delete [] array;
}
When you swap the values in array using
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
also swap the values(pointers) in point_array:
Point* tmpPoint = point_array[i];
point_array[i] = point_array[j];
point_array[j] = tmpPoint;
First you need to iterate over both arrays at the same time and calculate their distances. As you calculated their distances you can add them to a list, or another array. But while you are adding the distances to the list, add them in sorted order. You can have a method AddDistance(double distance). The first incoming distance goes into the sorted array as the first element. Then when the next one comes, you check it's value and compare it to all the other elements in the array. Here is pseudo code that can do the job for you:
double sortedDistances[100];
int sortedDistancesSize;
void InsertDistance(double distance)
{
int i=0;
for(i=0; i < sortedDistancesSize, sortedDistances[i] < distance; ++i);
InsertNewDistance(distance, i);
}
Your InsertNewDistance method should insert the given distance at position "i" and shift the contents of the array after position "i" to the right.

Average of odd cells?

For an exercise I am doing, I am supposed to find out the average of the items contained in odd numbered cells of an array and some other things. Finding the average of the odd numbered cells in the only thing I'm having a problem with. Here is my code, what am I doing wrong? The final function is the odd numbered cells average function. Thanks.
#include <iostream>
#include <iomanip>
using namespace std;
const int SIZE = 1000;
int randoms[SIZE];
int sum2 = 0;
int top = 0;
int maximum = 0;
int highest(int randoms[]);
int findsum(int randoms[]);
int average(int randoms[], int sum);
int oddavg(int randoms[]);
int main()
{
int sum = 0;
int top = 0;
int avg = 0;
int oddaverage = 0;
for (int i = 0; i < SIZE; i++)
{
randoms[i] = (rand() % 5000 + 1);
cout << randoms[i] << setw(10) << " ";
}
cout << endl << endl;
cout << "The sum of the values in the array is ";
sum = findsum(randoms);
cout << sum << endl;
cout << endl << endl;
cout << "The highest value in the array is ";
top = highest(randoms);
cout << top << endl;
cout << endl << endl;
cout << "The average of all of the numbers in the array is ";
avg = average(randoms, sum);
cout << avg << endl;
cout << endl << endl;
cout << "The average of all of the numbers in the odd cells is ";
oddaverage = oddavg(randoms);
}
int findsum(int randoms[])
{
for (int i = 0; i < SIZE; i++)
{
sum2 += randoms[i];
}
return sum2;
}
int highest(int randoms[])
{
for (int i = 0; i < SIZE; i++)
{
if (randoms[i] > maximum)
{
maximum = randoms[i];
}
}
top = maximum;
return top;
}
int average(int randoms[], int sum)
{
int avg = 0;
for (int i = 0; i < SIZE; i++)
{
avg = (sum / SIZE);
}
return avg;
}
int oddavg(int randoms[])
{
int avg = 0;
int sum = 0;
for (int i = 0; i < SIZE; i++)
{
if (randoms[i] / 2 == 1)
{
sum += randoms[i];
}
}
avg = sum / SIZE;
return avg;
}
Doing the odd/even test (using modulo as many have suggested) in this case is totally redundant, since the loop doesn't do anything else.
You can just use a stride of 2 and start at the first odd element:
for (int i = 1; i < SIZE; i += 2)
{
sum += randoms[i];
}
Then it's just a matter of dividing out by half of SIZE. If that number is even, then there are SIZE/2 odd numbers. If it's odd, then there are lbound(SIZE/2)+1 odd numbers. Fortunately, you can take advantage of integer truncation and just do:
double avg = double(sum) / double((SIZE+1) / 2);
And you don't even have to worry about divide-by-zero =)
should be if (randoms[i] % 2 == 1)
Also you need to count the number of odd numbers.
randoms[i] / 2 == 1, this will be true only when a cell value is 2 or 3, this is certainly not what you need to do.
If you need to sum values of cells with odds index then it should be if (i % 2 == 1). If instead you are looking for odd values (in any cell) it should be if (randoms[i] % 2 == 1).
Mind that % is the modulo operation which returns the integer remainder of the integer division.
And since you are calculating an average you should divide by the found amount of elements, not by the total.
int oddavg(int randoms[])
{
int cnt = 0;
int avg = 0;
for (int i = 0; i < SIZE; i++)
{
if ( randoms[i] % 2 != 0 )
{
++cnt;
avg += randoms[i];
}
}
return ( cnt == 0 ? avg : avg / cnt );
}