This question already has answers here:
How do I use arrays in C++?
(5 answers)
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 8 years ago.
I was implementing a version of the closest pair problem using the algorithmic technique of divide and conquer. However, when I try and compile my code, in several spots I get the error "Expected constant expression". I am aware that arrays are supposed to have constant values in them, but I'm not quite sure what's wrong in this case. I tried to research solutions and many people suggested using malloc, but it seems to be generally frowned upon. Would someone be able to help me fix this? Below is the code with the errors commented hopefully well enough that you can see them. Thank you so much in advance for your help, I really appreciate it!
#include <iostream>
#include <float.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
//A struct to represent the points on an x,y plane
struct Point{
int x, y;
};
//function to sort x coordinates
int compareX(const void* a, const void* b){
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->x - p2->x);
}
//function to sort y coordinates
int compareY(const void* a, const void* b){
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->y - p2->y);
}
//function to find the distance between any two points
float dist(Point p1, Point p2){
return sqrt( (float)(p1.x - p2.x) * (p1.x - p2.x) +
(float)(p1.y - p2.y) * (p1.y - p2.y)
);
}
//utility function to find the minimum of any two float values
float min(float x, float y){
if(x < y)
return x;
else
return y;
}
//brute force function to find the closest of two points
float bruteforce(Point P[], int n){
float min = FLT_MAX;
for(int i=0; i<n; i++){
for(int j = i+1; j < n; j++)
if(dist(P[i], P[j]) < min)
min = dist(P[i], P[j]);
}
return min;
}
//function to find the distance between the closest points of a given size
float closestArray(Point array1[], int size, float d){
float min = d; //initialize the minimum distance as d
//go through the points 1 by 1 and try the next until the difference is smaller than d
for (int i=0; i < size; i++)
for (int j= i + 1; j< size && (array1[i].y - array1[i].y) < min; j++)
if(dist(array1[i],array1[j]) < min)
min = dist(array1[i], array1[j]);
return min;
}
float closestPoint(Point Px[], Point Py[], int n){
if(n <= 3)
return bruteforce(Px, n);
//find the middle point
int mid = n/2;
Point midPoint = Px[mid];
//divide the points along the vertical line
Point Pyleft[mid + 1]; //left of vertical line <--- ERROR
Point Pyright[n-mid-1]; //right of vertical line <--- ERROR
int li = 0; //index of left subarray
int ri = 0; //index of right subarray
for ( int i =0; i<n; i++){
if (Py[i].x <= midPoint.x)
Pyleft[li++] = Py[i];
else
Pyright[ri++] = Py[i];
}
//calculate the smallest ditance dl on the left middle point and dr on the right side
float dl = closestPoint(Px, Pyleft, mid);
float dr = closestPoint(Px + mid, Pyright, n-mid);
//find the smaller of the two distances
float d = min(dl, dr);
//build another array Q that contains points closer than d to the line passing through the middle
Point q[n]; // <--- ERROR
int j = 0;
for (int i = 0; i<n; i++)
if(abs(Py[i].x - midPoint.x) < d)
q[j] = Py[i], j++;
return min(d, closestArray(q, j, d) );
}
//function that finds the smallerst distance
float closest(Point P[], int n){
Point Px[n]; //<--- ERROR
Point Py[n]; //<---ERROR
for(int i=0; i < n; i++)
{
Px[i] = P[i];
Py[i] = P[i];
}
qsort(Px, n, sizeof(Point), compareX);
qsort(Py, n, sizeof(Point), compareY);
//recursive function to find smallest distance
return closestPoint(Px, Py, n);
}
int main()
{
Point P[] = {{2, 3}, {12, 30}, {40, 50}, {5, 1}, {12, 10}, {3, 4}};
int n = sizeof(P) / sizeof(P[0]);
cout << "The smallest distance is " << closest(P, n);
return 0;
}
Related
I'm trying to solve this problem by bruteforce, but it seems to run very slow when given 7 (which is 2*7 points).
Note: I only need to run it to maximum 2*8 points
Problem statement:
Given 2*N points in a 2d plane, connect them in pairs to form N line segments. Minimize the total length of all the line segments.
Example:
Input: 5 10 10 20 10 5 5 1 1 120 3 6 6 50 60 3 24 6 9 0 0
Output: 118.4
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
class point{
public:
double x, y;
};
double getLength(point a, point b){
return hypot((a.x - b.x), (a.y - b.y));
}
static double mini = INT_MAX;
void solve(vector <point> vec, double sum){
double prevSum = sum;
if(sum > mini){
return;
}
if(vec.size() == 2){
sum += getLength(vec[0], vec[1]);
mini = min(mini, sum);
return;
}
for(int i = 0; i < vec.size() - 1; i++){
for(int j = i + 1; j < vec.size(); j++){
sum = prevSum;
vector <point> temp = vec;
sum += getLength(temp[i], temp[j]);
temp.erase(temp.begin() + j);
temp.erase(temp.begin() + i);
solve(temp, sum);
}
}
}
int main(){
point temp;
int input;
double sum = 0;
cin >> input;
vector<point> vec;
for(int i = 0; i < 2 * input; i++){
cin >> temp.x >> temp.y;
vec.push_back(temp);
}
solve(vec, sum);
cout << fixed << setprecision(2) << mini << endl;
}
How can I speed up this code ?
I don't think this is what you are looking for but I mention it for completeness sake anyway. The problem can be formulated as a Mixed Integer Programming (MIP) problem.
We have distances:
d(i,j) = distance between point i and j (only needed for i<j)
and decision variables
x(i,j) = 1 if points i and j are connected (only needed for i<j)
0 otherwise
Then we can write:
Solving this problem can be done with widely available MIP solvers and leads to proven optimal solutions. A small example with 50 points:
You can solve this iteratively by using next_permutation() to go through all the permutations one by one. Apologies for the messy code, but this should show you how to do it:
struct Point {
Point(int x, int y) : x(x), y(y) {
}
bool operator< (const Point& rhs) {
const int key1 = y * 1000 + x;
const int key2 = rhs.y * 1000 + rhs.x;
return key1 < key2;
}
double dist(const Point& next) {
const double h = (double)(next.x - x);
const double v = (double)(next.y - y);
return sqrt(h*h + v*v);
}
int x, y;
};
You need the operator so you have some sort of sorting key for your points, so next_permutation can go through them in lexicographical increasing order.
double getShortestDist(std::vector p) {
double min = 200000;
std::sort(p.begin(), p.end());
while(std::next_permutation(p.begin(), p.end())) {
double sum = 0.0;
for (int i = 0; i < p.size(); i+= 2) {
sum += p[i].dist(p[i+1]);
}
if (sum < min) {
min = sum;
}
}
return min;
}
int main(int argc, char*argv[]) {
static const int arr[] = {
10, 10, 20, 10, 5, 5, 1, 1, 120, 3, 6, 6, 50, 60, 3, 24, 6, 9, 0, 0
};
std::vector<Point> test;
for (int i = 0; i < 20; i += 2) {
test.push_back(Point(arr[i], arr[i+1]));
printf("%d %d\n", arr[i], arr[i+1]);
}
printf("Output: %d, %f", test.size(), getShortestDist(test));
}
So I have decided to implement an algorithm based on vectors to solve the Closest pair of points problem (2D). It seems to work with easy cases like
1.2 4.5
2.4 1.2
3.3 1.1
4.4 4.4
7.7 1.1
1.1 2.1
8.6 1.9
3.3 9.0
And the output is correct (for this case it is 0.90554), but somebody has checked my code and said that there is an invalid memory reference somewhere. I've been really struggling with this piece of code but I've give up, there is no way to find what is wrong (bc the cases I try work!).
I would really appreciate if somebody could enlighten me!
Thanks in advance!
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
struct Point { double x, y; };
bool compareX (Point p, Point q) { return p.x < q.x; }
bool compareY (Point p, Point q) { return p.y < q.y; }
float dist(Point p1, Point p2) {
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
double min_dist (vector<Point> pointsX, vector<Point> pointsY, int n) {
// BASE CASE.
if (n <= 3) {
double min = __DBL_MAX__;
for (int i = 0; i < n; ++i)
for (int j = i +1 ; j < n; ++j)
if (dist(pointsX[i], pointsX[j]) < min)
min = dist(pointsX[i], pointsX[j]);
return min;
}
// Step 1: Find the middle point.
int mid = n/2;
Point mid_point = pointsX[mid];
// Step 2: Divide the set in two equal-sized parts (left and right).
vector<Point> pointsY_left;
vector<Point> pointsY_right;
vector<Point> pointsX_left;
vector<Point> pointsX_right;
for (int i = 0; i < n; ++i) {
if (i < mid and pointsY[i].x <= mid_point.x) pointsY_left.push_back(pointsY[i]);
else pointsY_right.push_back(pointsY[i]);
}
for (int i = 0; i < n; ++i) {
if (i < mid and pointsX[i].x <= mid_point.x) pointsX_left.push_back(pointsX[i]);
else pointsX_right.push_back(pointsX[i]);
}
// Step 3: Calculate the smaller distance at left and right parts recursively.
double d_left = min_dist(pointsX_left, pointsY_left, mid);
double d_right = min_dist(pointsX_right , pointsY_right, n - mid);
// Let d be the minimal of the 2 distances.
double d = min (d_left, d_right);
// Eliminate points that are farther than d <=> Create a strip that contains
// points closer than d.
vector<Point> strip;
for (int i = 0; i < n; ++i) if (abs(pointsY[i].x - mid_point.x) < d) strip.push_back(pointsY[i]);
// Scan the points from the strip and compute the dstances of each point to its 7 neighbours.
// Pick all points one by one and try the next points until the difference
// between y coordinates is smaller than d.
for (int i = 0; i < int(strip.size()); ++i)
for (int j = i + 1; j < int(strip.size()) and (strip[j].y - strip[i].y) < d; ++j)
if (dist (strip[i], strip[j]) < d)
d = dist(strip[i], strip[j]);
return d;
}
double closest(const vector<Point>& points) {
// Initial step: sort points accroding to their coordinates.
vector<Point> pointsX, pointsY;
pointsX = pointsY = points;
sort(pointsX.begin(), pointsX.end(), compareX);
sort(pointsY.begin(), pointsY.end(), compareY);
return min_dist (pointsX, pointsY, int(points.size()));
}
int main() {
cout.setf(ios::fixed);
cout.precision(5);
vector<Point> points;
double x, y;
while (cin >> x >> y) {
Point p = {x, y};
points.push_back(p);
}
cout << closest (points) << endl;
}
Looks like problem is in Step 2. You have two different conditions i < mid and pointsY[i].x <= mid_point.x and i < mid and pointsX[i].x <= mid_point.x, but in the following code you suppose these conditions are equal. Probably you should replace these conditions with just i < mid.
// Step 1: Find the middle point.
int mid = n/2;
Point mid_point = pointsX[mid];
// Step 2: Divide the set in two equal-sized parts (left and right).
vector<Point> pointsY_left;
vector<Point> pointsY_right;
vector<Point> pointsX_left;
vector<Point> pointsX_right;
for (int i = 0; i < n; ++i) {
if (i < mid and pointsY[i].x <= mid_point.x) pointsY_left.push_back(pointsY[i]);
else pointsY_right.push_back(pointsY[i]);
}
for (int i = 0; i < n; ++i) {
if (i < mid and pointsX[i].x <= mid_point.x) pointsX_left.push_back(pointsX[i]);
else pointsX_right.push_back(pointsX[i]);
}
P.S. You can simply use constructor of vector:
vector<Point> pointsY_left( pointsY.cbegin(), pointsY.cbegin() + mid );
vector<Point> pointsY_right( pointsY.cbegin() + mid, pointsY.cend() );
vector<Point> pointsX_left( pointsX.cbegin(), pointsX.cbegin() + mid );
vector<Point> pointsX_right( pointsX.cbegin() + mid, pointsX.cend() );
I am new to C++ and I am using the Eigen library. I was wondering if there was a way to sum certain elements in a vector. For example, say I have a vector that is a 100 by 1 and I just want to sum the first 10 elements. Is there a way of doing that using the Eigen library?
What I am trying to do is this: say I have a vector that is 1000 by 1 and I want to take the mean of the first 10 elements, then the next 10 elements, and so on and store that in some vector. Hence I will have a vector of size 100 of the averages. Any thoughts or suggestions are greatly appreciated.
Here is the beginning steps I have in my code. I have a S_temp4vector that is 1000 by 1. Now I intialize a new vector S_A that I want to have as the vector of the means. Here is my messy sloppy code so far: (Note that my question resides in the crudeMonteCarlo function)
#include <iostream>
#include <cmath>
#include <math.h>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <random>
#include <time.h>
using namespace Eigen;
using namespace std;
void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n);
VectorXd time_vector(double min, double max, int n);
VectorXd call_payoff(VectorXd S, double K);
int main(){
int N = 100;
double K = 100;
double r = 0.2;
double S0 = 100;
double sigma = 0.4;
double T = 0.1;
int n = 10;
crudeMonteCarlo(N,K,r,S0,sigma,T,n);
return 0;
}
VectorXd time_vector(double min, double max, int n){
VectorXd m(n + 1);
double delta = (max-min)/n;
for(int i = 0; i <= n; i++){
m(i) = min + i*delta;
}
return m;
}
MatrixXd generateGaussianNoise(int M, int N){
MatrixXd Z(M,N);
static random_device rd;
static mt19937 e2(time(0));
normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
Z(i,j) = dist(e2);
}
}
return Z;
}
VectorXd call_payoff(VectorXd S, double K){
VectorXd C(S.size());
for(int i = 0; i < S.size(); i++){
if(S(i) - K > 0){
C(i) = S(i) - K;
}else{
C(i) = 0.0;
}
}
return C;
}
void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n){
// Create time vector
VectorXd tt = time_vector(0.0,T,n);
VectorXd t(n);
double dt = T/n;
for(int i = 0; i < n; i++){
t(i) = tt(i+1);
}
// Generate standard normal Z matrix
//MatrixXd Z = generateGaussianNoise(N,n);
// Generate the log normal stock process N times to get S_A for crude Monte Carlo
MatrixXd SS(N,n+1);
MatrixXd Z = generateGaussianNoise(N,n);
for(int i = 0; i < N; i++){
SS(i,0) = S0;
for(int j = 1; j <= n; j++){
SS(i,j) = SS(i,j-1)*exp((double) (r - pow(sigma,2.0))*dt + sigma*sqrt(dt)*(double)Z(i,j-1));
}
}
// This long bit of code gives me my S_A.....
Map<RowVectorXd> S_temp1(SS.data(), SS.size());
VectorXd S_temp2(S_temp1.size());
for(int i = 0; i < S_temp2.size(); i++){
S_temp2(i) = S_temp1(i);
}
VectorXd S_temp3(S_temp2.size() - N);
int count = 0;
for(int i = N; i < S_temp2.size(); i++){
S_temp3(count) = S_temp2(i);
count++;
}
VectorXd S_temp4(S_temp3.size());
for(int i = 0; i < S_temp4.size(); i++){
S_temp4(i) = S_temp3(i);
}
VectorXd S_A(N);
S_A(0) = (S_temp4(0) + S_temp4(1) + S_temp4(2) + S_temp4(3) + S_temp4(4) + S_temp4(5) + S_temp4(6) + S_temp4(7) + S_temp4(8) + S_temp4(9))/(n);
S_A(1) = (S_temp4(10) + S_temp4(11) + S_temp4(12) + S_temp4(13) + S_temp4(14) + S_temp4(15) + S_temp4(16) + S_temp4(17) + S_temp4(18) + S_temp4(19))/(n);
int count1 = 0;
for(int i = 0; i < S_temp4.size(); i++){
S_A(count1) =
}
// Calculate payoff of Asian option
//VectorXd call_fun = call_payoff(S_A,K);
}
This question includes a lot of code, which makes it hard to understand the question you're trying to ask. Consider including only the code specific to your question.
In any case, you can use Eigen directly to do all of these things quite simply. In Eigen, Vectors are just matrices with 1 column, so all of the reasoning here is directly applicable to what you've written.
const Eigen::Matrix<double, 100, 1> v = Eigen::Matrix<double, 100, 1>::Random();
const int num_rows = 10;
const int num_cols = 1;
const int starting_row = 0;
const int starting_col = 0;
const double sum_of_first_ten = v.block(starting_row, starting_col, num_rows, num_cols).sum();
const double mean_of_first_ten = sum_of_first_ten / num_rows;
In summary: You can use .block to get a block object, .sum() to sum that block, and then conventional division to get the mean.
You can reshape the input using Map and then do all sub-summations at once without any loop:
VectorXd A(1000); // input
Map<MatrixXd> B(A.data(), 10, A.size()/10); // reshaped version, no copy
VectorXd res = B.colwise().mean(); // partial reduction, you can also use .sum(), .minCoeff(), etc.
The Eigen documentation at https://eigen.tuxfamily.org/dox/group__TutorialBlockOperations.html says an Eigen block is a rectangular part of a matrix or array accessed by matrix.block(i,j,p,q) where i and j are the starting values (eg 0 and 0) and p and q are the block size (eg 10 and 1). Presumably you would then iterate i in steps of 10, and use std::accumulate or perhaps an explicit summation to find the mean of matrix.block(i,0,10,1).
I was writing this code to find the minimum distance between 2 points.The code I have written gives me the minimum distance correctly but does not give the correct coordinates from which the minimum distance is computed.Kindly help me identify the problem according to me this is the correct approach to print the points as well along with the minimum distance.
#include<bits/stdc++.h>
#define FOR(i,N) for(int i=0;i<(N);i++)
#define rep(i,a,n) for(int i=(a);i<(n);i++)
using namespace std;
struct point {
int x;
int y;
};
typedef struct point point;
void printarr(point arr[], int n) {for(int i = 0; i < n; i++) cout <<
arr[i].x << " " << arr[i].y << endl; cout << endl;
bool comparex(const point& X, const point& Y) { return X.x < Y.x; }
bool comparey(const point& X, const point& Y) { return X.y < Y.y; }
float getdis(point X, point Y) { return sqrt((X.x - Y.x)*(X.x - Y.x) + (X.y
- Y.y)*(X.y - Y.y)); }
float brutedis(point P[], int n, point A[]) {
float d = INT_MAX;
float temp;
FOR(i, n) {
rep(j, i+1, n) {
temp = getdis(P[i],P[j]);
if(temp < d) {
d = temp;
A[0].x = P[i].x; A[0].y = P[i].y;
A[1].x = P[j].x ; A[1].y = P[j].y;
}
}
}
return d;
}
float stripdis(point P[], int n, float d, point A[]) {
float temp = d;
float dis;
sort(P, P + n, comparey);
FOR(i, n) {
rep(j,i+1,n) {
if(abs(P[j].y - P[i].y) < d) {
dis = getdis(P[j], P[i]);
if(dis < temp) {
temp = dis;
A[0].x = P[i].x; A[0].y = P[i].y;
A[1].x = P[j].x ; A[1].y = P[j].y;
}
}
}
}
return temp;
}
float solve(point P[], int n, point A[]) {
if(n <= 3) return brutedis(P, n, A);
int mid = n/2;
point M = P[mid];
float d = min(solve(P, mid, A), solve(P+mid, n-mid, A));
point strip[n];
int j = 0;
int i = 0;
while(i < n) {
if(abs(P[i].x - M.x) < d) strip[j++] = P[i];
i++;
}
return min(d, stripdis(strip, j, d, A));
}
int main() {
point P[] = {{0, 0}, {-4,1}, {-7, -2}, {4, 5}, {1, 1}};
int n = sizeof(P) / sizeof(P[0]);
sort(P, P+n, comparex);
point A[2];
cout << "Minimum Distance = " << solve(P, n, A) << "\n";
printarr(A, 2);
//printarr(P, n);
return 0;
}
To the extent I can follow your badly formatted code, brutedis unconditionally modifies A[] and it gets called again after you have found the right answer (but don't know you found the right answer).
So if the first call were best in min(solve(P, mid, A), solve(P+mid, n-mid, A)); the second could still call brutedis and destroy A[]
You call solve twice, both giving it A as the parameter. Each of these calls always overwrite A, but only one returns the correct answer. And they both call brutedis that also always overwrites A.
The easiest way to fix this is to introduce an additional parameter to all these functions, that would contain the minimal distance found so far, the same way you did with stripdis.
float solve(point P[], int n, float d, point A[]) {
if(n <= 3) return brutedis(P, n, d, A);
...
d = solve(P, mid, d, A);
d = solve(P+mid, n-mid, d, A);
d = stripdis(strip, j, d, A));
...
float brutedis(point P[], int n, float d, point A[])
{
// float d = INT_MAX -- Not needed
Thus A will only be overeritten if the distance between the new pair of points is globally minimal so far.
No need to call min as each function already keeps the minimum of d and the distance it finds.
That is because after getting the correct coordinates in "A" array, you are again updating that. just look for the below statement in your code:
float d = min(solve(P, mid, A), solve(P+mid, n-mid, A));
this will give correct minimum distance but not correct coordinates. Just think about it, if your first call to solve, in the above statement has the minimum distance coordinates, then your second call is going to modify the coordinates in A[]. take a pen and paper and try to solve for the coordinates you have, it'll give you better understanding.
Exercise 13, from Chapter 12 of Stroustrup's Programming principles and practice using c++.
A superellipse is a two-dimensional shape defined by the equation
Look up superellipse on the web to get a better idea of what such
shapes look like. Write a program that draws "starlike" patterns by
connecting points on a superellipse. Take a, b, m, n, and N as
arguments.
Select N points on the superellipse defined by a, b, m,
and n. Make the points equally spaced for some definition of
"equal" Connect each of those N points to one or more other points
(if you like you can make the number of points connected to another
argument or just use N-1, i.e., all me orner points).
i have a vector that contains points with which i can build the superellipse
i cant get the second part of exercise - how to find N-points lying on superellipse to build stars?
thanks
//------------------------------------------------------------------------------
struct Point {
int x, y;
Point(int xx, int yy) : x(xx), y(yy) { }
Point() :x(0), y(0) { }
};
//------------------------------------------------------------------------------
int sgn(double d) {
if (d < 0)
return -1;
if (d == 0)
return 0;
if (d > 0)
return 1;
// exception
error("sgn: something gone wrong\n");
}
//------------------------------------------------------------------------------
vector<Point> superellipse(double a, double b, double m, double n, double precision = 0.01, int xCenter = 200, int yCenter = 200) {
if (precision >= 1.00 || precision < 0.001)
error ("use numbers from range [0.001 ; 1.00) for precision parametr\n");
vector<Point> points;
Point temp;
Point P;
for (double d = -1.0; d < 1.00; d += precision) {
double t = d*M_PI;
int x = pow((abs(cos(t))),2.0/m) * a * sgn(cos(t));
int y = pow((abs(sin(t))),2.0/n) * b * sgn(sin(t));
P = Point(x + xCenter, y + yCenter);
if (P != temp) // ignore dublicates
points.push_back(P);
temp = P;
}
return points;
}
//------------------------------------------------------------------------------
1.scratch
vector<Point> superellipse (/*...*/) {
/* */
return points;
}
2.put
class Superellipse {
std::vector<Point> _points;
void draw_connected(const Point& A, const Point& B);
public:
void draw_star(/* params */);
Superellipse(/* params*/){
/* initialize _points*/
}
};
i cant get the second part of exercise - how to find N-points lying on
superellipse to build stars?
???
You already have the points in your vector.
http://www.stroustrup.com/Programming/programming_ch12.pdf
if you like you can make the number of points connect to another
argument or just use N–1, i.e., all the other points
void Superellipse::draw_star (/* */){
int N = _points.size();
for (int i = 0; i < N; ++i) {
for (int j = i + 1; j < N; ++j) {
draw_connected (_points[i], _points[j]);
}
}
}