finding all closest point pairs if multiple closest pairs exist - c++

The following code is for finding the closest point pairs problem in Introduction to Programming with C++ liang textbook. and I'm trying to edit it so it can find all closest point pairs if multiple closest pairs exist.
#include <iostream>
#include <cmath>
using namespace std;
/** Compute the distance between two points (x1, y1) and (x2, y2) */
double getDistance(double x1, double y1, double x2, double y2)
{
return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
int main()
{
const int NUMBER_OF_POINTS = 8;
// Each row in points represents a point
double points[NUMBER_OF_POINTS][2];
cout << "Enter " << NUMBER_OF_POINTS << " points: ";
for (int i = 0; i < NUMBER_OF_POINTS; i++)
cin >> points[i][0] >> points[i][1];
// p1 and p2 are the indices in the points array
int p1 = 0, p2 = 1; // Initial two points
double shortestDistance = getDistance(points[p1][0], points[p1][1],
points[p2][0], points[p2][1]); // Initialize
// Compute distance for every two points
for (int i = 0; i < NUMBER_OF_POINTS; i++)
{
for (int j = i + 1; j < NUMBER_OF_POINTS; j++)
{
double distance = getDistance(points[i][0], points[i][1],
points[j][0], points[j][1]); // Find distance
if (shortestDistance > distance)
{
p1 = i; // Update p1
p2 = j; // Update p2
shortestDistance = distance; // Update shortestDistance
}
}
}
// Display result
cout << "The closest two points are " <<
"(" << points[p1][0] << ", " << points[p1][1] << ") and (" <<
points[p2][0] << ", " << points[p2][1] << ")";
return 0;
}
I solved it by using a new array, distance-points , and save the distance with the points pair whenever the distance is calculated, after that I loop over the new array and print out the shortest distance, but I think there is smarter solution for sure, Im quite new in programming :)
double distance_points[28][5];
int f = 0 ;
// Compute distance for every two points
for (int i = 0; i < NUMBER_OF_POINTS; i++)
{
for (int j = i + 1; j < NUMBER_OF_POINTS; j++)
{
double distance = getDistance(points[i][0], points[i][1],
points[j][0], points[j][1]); // Find distance
distance_points[f][0] = distance;
distance_points[f][1] = points[i][0];
distance_points[f][2] = points[i][1];
distance_points[f][3] = points[j][0];
distance_points[f][4] = points[j][1];
f++;
}
}

You may change your algorithm to stock results in vector:
std::vector<int> p1, p2;
double shortestDistance = getDistance(points[p1][0], points[p1][1],
points[p2][0], points[p2][1]); // Initialize
for (int i = 0; i < NUMBER_OF_POINTS; i++) {
for (int j = i + 1; j < NUMBER_OF_POINTS; j++) {
const double distance = getDistance(points[i][0], points[i][1],
points[j][0], points[j][1]);
if (shortestDistance >= distance) {
if (shortestDistance > distance) {
p1.clear();
p2.clear();
shortestDistance = distance; // Update shortestDistance
}
p1.push_back(i); // Update p1
p2.push_back(j); // Update p2
}
}
}

Related

Cross the yard without getting wet

Here is the question:
There is a house with a backyard which is square bounded by
coordinates (0,0) in the southwest to (1000,1000) in
the northeast. In this yard there are a number of water sprinklers
placed to keep the lawn soaked in the middle of the summer. However,
it might or might not be possible to cross the yard without getting
soaked and without leaving the yard?
Input The input starts with a line containing an integer 1≤n≤1000, the
number of water sprinklers. A line follows for each sprinkler,
containing three integers: the (x,y)(x,y) location of the sprinkler
(0≤x,y,≤10000) and its range r (1≤r≤1000). The sprinklers will soak
anybody passing strictly within the range of the sprinkler (i.e.,
within distance strictly less than r).
The house is located on the west side (x=0) and a path is needed to
the east side of the yard (x=1000).
Output If you can find a path through the yard, output four real
numbers, separated by spaces, rounded to two digits after the decimal
place. These should be the coordinates at which you may enter and
leave the yard, respectively. If you can enter and leave at several
places, give the results with the highest y. If there is no way to get
through the yard without getting soaked, print a line containing
“IMPOSSIBLE”.
Sample Input
3
500 500 499
0 0 999
1000 1000 200
Sample output
0.00 1000.00 1000.00 800.00
Here is my thought process:
Define circle objects with x,y,r and write a function to determine if a given point is wet or not(inside the circle or not) on the circumference is not wet btw.
class circle {
int h;
int k;
int r;
public:
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
};
bool iswet(pair<int,int>* p){
if (pow(this->r - 0.001, 2) > (pow(p->first - this->h, 2) +
pow(p->second - this->k, 2) ) ) {
return true;
}
else
return false;
};
Then implement a depth first search, prioritizing to go up and right whenever possible.
However since circles are not guaranteed to be pass on integer coordinates an the result is expected in floats with double precision (xxx.xx). So if we keep everything in integers the grid suddenly becomes 100,000 x 100,000 which is way too big. Also the time limit is 1 sec.
So I thought ok lets stick to 1000x1000 and work with floats instead. Loop over int coordinates and whenever I hit a sprinkle just snap in the perimeter of the circle since we are safe in the perimeter. But in that case could not figure out how DFS work.
Here is the latest trial
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <utility>
#include <unordered_set>
#include <iomanip>
using namespace std;
const int MAXY = 1e3;
const int MAXX = 1e3;
const int MINY = 0;
const int MINX = 0;
struct pair_hash {
inline std::size_t operator()(const std::pair<int,int> & v) const {
return v.first*31+v.second;
}
};
class circle {
int h;
int k;
int r;
public:
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
};
bool iswet(pair<float,float>* p){
if (pow(this->r - 0.001, 2) > (pow(p->first - this->h, 2) + pow(p->second - this->k, 2) ) ) {
this->closest_pair(p);
return true;
}
else
return false;
};
void closest_pair(pair<float,float>* p){
float vx = p->first - this->h;
float vy = p->second - this->k;
float magv = sqrt(vx * vx + vy * vy);
p->first = this->h + vx / magv * this->r;
p->second = this->k + vy / magv * this->r;
}
};
static bool test_sprinkles(vector<circle> &sprinkles, pair<float,float>* p){
for (int k = 0; k < sprinkles.size(); k++)
if (sprinkles[k].iswet(p)) return false;
return true;
}
int main(){
int n; // number of sprinkles
while (cin >> n){
vector<circle> sprinkles_array;
sprinkles_array.reserve(n);
int h, k, r;
while (n--){
cin >> h >> k >> r;
sprinkles_array.push_back(circle(h, k, r));
}/* code */
pair<float,float> enter = make_pair(0, MAXY);
deque<pair<float,float>> mystack;
mystack.push_back(enter);
pair<float,float>* cp;
bool found = false;
unordered_set<pair<float, float>, pair_hash> visited;
while (!mystack.empty()){
cp = &mystack.back();
if (cp->first == MAXX) {
found = true;
break;
}
visited.insert(*cp);
if (cp->second > MAXY || cp->second < MINY || cp ->first < MINX ) {
visited.insert(*cp);
mystack.pop_back();
continue;
}
if (!test_sprinkles(sprinkles_array,cp)) {
continue;
}
pair<int,int> newpair = make_pair(cp->first, cp->second + 1);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first + 1 , cp->second);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first, cp->second - 1);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first - 1, cp->second);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
mystack.pop_back();
}
cout << setprecision(2);
cout << fixed;
if (found){
double xin = mystack.front().first;
double yin = mystack.front().second;
pair <float, float> p = mystack.back();
p.second++;
for (int k = 0; k < sprinkles_array.size(); k++)
if (sprinkles_array[k].iswet(&p)) break;
double xout = p.first;
double yout = p.second;
cout << xin << " " << yin << " " << xout << " " << yout << endl;
}
else
{
cout << "IMPOSSIBLE" << endl;
}
}
}
Yes #JosephIreland is right. Solved it with grouping intersecting (not touching) circles. Then these groups have maxy and min y coordinates. If it exceeds the yard miny and maxy the way is blocked.
Then these groups also have upper and lower intersection points with x=0 and x=1000 lines. If the upper points are larger than the yard maxy then the maximum entry/exit points are lower entery points.
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include <iomanip>
using namespace std;
const int MAXY = 1e3;
const int MAXX = 1e3;
const int MINY = 0;
const int MINX = 0;
struct circle {
int h;
int k;
int r;
float maxy;
float miny;
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
this->miny = this->k - r;
this->maxy = this->k + r;
};
};
struct group {
float maxy = -1;
float miny = -1;
vector<circle*> circles;
float upper_endy = -1;
float upper_starty = -1;
float lower_endy = -1;
float lower_starty = -1;
void add_circle(circle& c){
if ((c.maxy > this->maxy) || this->circles.empty() ) this->maxy = c.maxy;
if ((c.miny < this->miny) || this->circles.empty() ) this->miny = c.miny;
this->circles.push_back(&c);
// find where it crosses x=minx and x= maxx
float root = sqrt(pow(c.r, 2) - pow(MINX - c.h, 2));
float y1 = root + c.k;
float y2 = -root + c.k;
if (y1 > this->upper_starty) this->upper_starty = y1;
if (y2 > this->lower_starty) this->lower_starty = y2;
root = sqrt(pow(c.r, 2) - pow(MAXX - c.h, 2));
y1 = root + c.k;
y2 = -root + c.k;
if (y1 > this->upper_endy) this->upper_endy = y1;
if (y2 > this->lower_endy) this->lower_endy = y2;
};
bool does_intersect(circle& c1){
for(circle* c2 : circles){
float dist = sqrt(pow(c1.h - c2->h,2)) + sqrt(pow(c1.k - c2->k,2));
(dist < (c1.r + c2->r)) ? true : false;
};
};
};
int main(){
int n; // number of sprinkles
while (cin >> n){
vector<circle> sprinkles_array;
sprinkles_array.reserve(n);
int h, k, r;
while (n--){
cin >> h >> k >> r;
sprinkles_array.push_back(circle(h, k, r));
}/* code */
vector<group> groups;
group newgroup;
newgroup.add_circle(sprinkles_array[0]);
groups.push_back(newgroup);
for (int i = 1; i < sprinkles_array.size(); i++){
bool no_group = true;
for (group g:groups){
if (g.does_intersect(sprinkles_array[i])){
g.add_circle(sprinkles_array[i]);
no_group = false;
break;
}
}
if (no_group) {
group newgroup;
newgroup.add_circle(sprinkles_array[i]);
groups.push_back(newgroup);
}
}
float entery = MAXY;
float exity = MAXY;
bool found = true;
for (group g : groups){
if ((g.miny < MINY) && (g.maxy > MAXY)){
found = false;
break;
}
if (g.upper_starty > entery)
entery = g.lower_starty;
if (g.upper_endy > exity)
exity = g.lower_endy;
}
cout << setprecision(2);
cout << fixed;
if (found){
cout << float(MINX) << " " << entery << " " << float(MAXX) << " " << exity << endl;
}
else
{
cout << "IMPOSSIBLE" << endl;
}
}
}

Generate vector elements from previous elements

I would like to build a vector of vectors which is really a tree. I have the seed value and going forward, I multiply the seed with u to get the up value and with d to get the down value. I have the below snippet that does what I want but can you please suggest a more efficient approach?
void short_rate_lattice() {
double r00 = 0.06;
double u = 1.25;
double d = 0.9;
int num_periods = 5;
vector<vector<double>> short_rates(num_periods + 1);
short_rates[0].push_back(r00);
for (int i = 1; i <= num_periods; ++i) {
for (int j = 0; j < i; ++j) {
short_rates[i].push_back(d * short_rates[i - 1][j]);
}
short_rates[i].push_back(u * short_rates[i - 1][i - 1]);
}
cout << "short_rates vector is populated" << endl;
}

Particles in a 2D box - rounding errors when calculating the energy

I am trying to calculate distances between particles in a box. If the distance calculated is greater than a preset cut-off distance, then the potential energy is 0. Otherwise, it is 1.
There are some rounding issues I think and I am not familiar with variable types and passing variables through functions to know what to do next.
The error
When I calculate d0 by hand I get d0 = 0.070 - this is not what the computer gets! The computer gets a number on the order of e-310.
All of the calculated distances (dij) are no shorter than 1/14, which is much larger than e-310. According to my if statement, if dij>d0, then U=0, so I should get a total energy of 0, but this is what I get:
d0 is 6.95322e-310
i is 0 j is 1 dij is 0.0714286 d0 is 6.95322e-310 Uij is 1
.....
Energy of the system is 24976
Please let me know if I could provide any more information. I did not include the entirety of my code, but the other portion involves no manipulation of d0.
I copied the relevant pieces of code below
Part 1: relevant box data
class Vector {
public:
double x;
double y;
Vector() {
}
Vector (double x_, double y_) {
x = x_;
y = y_;
}
double len() {
return sqrt(x*x + y*y);
}
double lenSqr() {
return x*x + y*y;
}
};
class Atom
{
public:
Vector pos;
Vector vel;
Vector force;
Atom (double x_, double y_) {
pos = Vector(x_, y_);
}
};
class BoxData
{
public:
const double Len = 1.;
const double LenHalf = 0.5 * Len;
long double d = 1. / 14; // d is the distance between each atom
in the initial trigonal lattice
int nu = 7; // auxillary parameter - will be varied
long double d0 = d * (1 - 2^(nu - 8)); // cutoff distance
double alpha = d - d0; // maximum allowed displacement
};
int main() {
// Initialize box
LoadBox();
// Institute a for loop here
SystemEnergy();
MonteCarloMove();
return 0;
}
//Putting atoms into box
void LoadBox()
{
ofstream myfile("init.dat", ios::out);
//Load atoms in box in triangular offset lattice
const double x_shift = 1. / 14;
const double y_shift = 1. / 16;
double x = 0;
double y = 0;
double x_offset = 0;
for (y = 0; y <= 1. - y_shift; y += y_shift) {
for (x = x_offset; x < 0.99; x += x_shift) {
// create atom in position (x, y)
// and store it in array of atoms
atoms.push_back(Atom(x, y));
}
// every new row flip offset 0 -> 1/28 -> 0 -> 1/28...
if (x_offset < x_shift / 4) {
x_offset = x_shift / 2;
} else {
x_offset = 0.0;
}
}
const int numAtoms = atoms.size();
//print the position of each atom in the file init.dat
for (int i = 0; i < numAtoms; i++) {
myfile << "x is " << atoms[i].pos.x << " y is " << atoms[i].pos.y << endl;
}
myfile.close();
}
Part 2 : Energy calculation
vector<Atom> atoms;
BoxData box_;
void SystemEnergy()
{
ofstream myfile("energy.dat", ios::out);
double box_Len, box_LenHalf, box_d0;
double dij; // distance between two atoms
double Uij; // energy between two particles
double UTotal = 0;
double pbcx, pbcy; // pbc -> periodic boundary condition
double dx, dy;
myfile << "d0 is " << box_d0 << endl;
// define the number of atoms as the size of the array of atoms
const int numAtoms = atoms.size();
//pick atoms
for (int i=0; i<numAtoms-1; i++) { // pick one atom -> "Atom a"
Atom &a = atoms[i];
for (int j=i+1; j<numAtoms; j++) { // pick another atom -> "Atom b"
Atom &b = atoms[j];
dx = a.pos.x - b.pos.x;
dy = a.pos.y - b.pos.y;
pbcx = 0.0;
pbcy = 0.0;
// enforce periodic boundary conditions
if(dx > box_LenHalf) pbcx =- box_Len;
if(dx < -box_LenHalf) pbcx =+ box_Len;
if(dy > box_LenHalf) pbcy =- box_Len;
if(dy < -box_LenHalf) pbcy =+ box_Len;
dx += pbcx;
dy += pbcy;
// calculate distance between atoms
dij = sqrt(dx*dx + dy*dy);
// compare dij to the cutoff distance to determine energy
if (dij > box_d0) {
Uij = 0;
} else {
Uij = 1;
}
myfile << "i is " << i << " j is " << j << " dij is " << dij << " d0 is " << box_d0 << " Uij is " << Uij << endl;
UTotal += Uij; // sum the energies
}
}
myfile << "Energy of the system is " << UTotal << endl;
myfile.close();
}
Sorry for the formatting issues - getting the hang of copy/pasting to the forum.

Initializing dynamic pointer to multidimensional array

I am new to programming and am trying to implement A star search algorithm on C++. I am having segmentation fault:11 because of not initializing my pointer. I have tried it several different ways to no avail.
I am still confused about the whole pointer and dynamic memory allocation concept.
Can anyone help me figure it out? Thank you.
#include <iostream>
#include <vector>
#include <fstream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
using namespace std;
// Definition of the heuristic. The heuristic in this problem is the distance between
// two coordinates
double heuristic(double x1, double y1, double x2, double y2) {
double dx, dy;
dx = x1 - x2;
dy = y1 - y2;
return sqrt(dx*dx - dy*dy);
//return sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2));
}
// ----- A Star Search Algorithm (f = g + h)----
double** a_star_search(double points[][2]) {
int count = 1;
double** points1 = NULL;
// points1[10][2];
double x1 = points[0][0];
double y1 = points[0][1];
points1[count - 1][0] = x1;
points1[count - 1][1] = y1;
while (count <= 10) {
double tempx1;
double tempy1;
double distance = 10000000;
for (int i = 0; i < 10; i++) {
if (points[i][0] != 0 && points[i][1] != 0) {
double distance2 = heuristic(x1, y1, points[i][0], points[i][1]);
if (distance2 < distance) {
tempx1 = points[i][0];
tempy1 = points[i][1];
distance = distance2;
}
}
}
x1 = tempx1;
y1 = tempy1;
count++;
points1[count - 1][0] = x1;
points1[count - 1][1] = y1;
}
return points1;
}
int main() {
double points[7][2];
int counter = 0;
ifstream infile("waypoints.txt");
int a, b;
while (infile >> a >> b)
{
points[counter][0] = a;
points[counter][1] = b;
counter++;
}
points[6][0] = points[0][0];
points[6][1] = points[0][1];
double** points1 = a_star_search(points);
cout << "Initial Sequence: ";
for (int i = 0;i < 7;i++) {
cout << "(" <<points[i][0] << " , " << points[i][1] << "), ";
}
cout << "\n\nOptimized Sequence: ";
for (int i = 0;i < 7;i++) {
cout << "(" << points1[i][0] << " , " << points1[i][1] << "), ";
}
cout << "\n\nTotal Distance after A* search: ";
double totaldistance = 0;
for (int i = 0;i < 6;i++) {
double dis = heuristic(points1[i][0], points1[i][1], points1[i + 1][0], points1[i + 1][1]);
cout << dis << "+";
totaldistance = totaldistance + dis;
}
cout<< "=" << totaldistance <<endl;
}
You are not allocating memory dynamically for double** points1 variable after setting it to NULL in your a_star_search function. As pointed out by #user4581301, use std::vector. This will simplify your code significantly and worth spending the time to learn STL containers.

Program ignoring condition?

In my code, I'm trying to prevent circles from overlapping so I specified it as a condition on the distance between the centres of the circles but it seems to not work all the time
as you can see :
could it be some kind of numerical precision rounding problem ?
Here is the relevant code (I can post the whole code if needed):
const double win_size = 800;
const double L = 50e-9; //box size (m)
const double k = 1.38e-23; // Boltzmann constant = 1.38e-23 J/K
const double R = 1.6e-10*30; //N2 radius = 1.6e-10 m
const double m = 4.65e-26; //N2 mass = 4.65e-26 kg
struct parameters{
double x;
double y;
double v_x;
double v_y;
};
bool empty_space(double x, double y, struct parameters gas[], int N, int i){
if (i == 0) return true;
for (int i = 0; i<N; i++){
if (pow(x-gas[i].x,2) + pow(y-gas[i].y,2) <= 4*R*R){
cout << gas[i].x << " " << gas[i].y << endl;
return false;
}
}
return true;
}
void initialize(struct parameters gas[], int N, double T){ // Sets initial conditions (velocity depends on temperature)
int tries = 0;
double x, y;
for (int i=0; i<N; i++){
if (tries == 10000){
cout << "Couldn't fit " << N << " molecules in the box, aborting simulation... " << endl;
exit(1);
}
x = R + (L - 2*R)*rand()/RAND_MAX;
y = R + (L - 2*R)*rand()/RAND_MAX;
if (empty_space(x,y,gas,N,i)){
gas[i].x = x;
gas[i].y = y;
}
else {
i--;
tries++;
}
gas[i].v_x = sqrt(2*k*T/m)*(1-2.0*rand()/RAND_MAX);
gas[i].v_y = (2*(rand()%2) - 1)*sqrt(2*k*T/m - pow(gas[i].v_x, 2));
}
}
void draw(int window, struct parameters gas[], int N, int automatic){
g2_pen(window,g2_ink(window,0.8,0.3,0.4));
for (int i=0; i<N; i++){
g2_circle(window,gas[i].x*win_size/L,gas[i].y*win_size/L,R*win_size/L);
}
g2_flush(window);
usleep(10000);
g2_pen(window,0);
g2_filled_rectangle(window,0,0,win_size,win_size);
if (!automatic) getchar();
}
The first debugging step is to print the coordinates of the circles that have clashed somehow, then see what the "distance" function is returning for their centers. My guess it it's somehow a rounding problem but this seems to be what you need to do next.