I'm trying to solve a classical algorithmic problem on Closest pair of points. To do this, I use an O(n log n) algorithm from CLRS.
Let me remind you what it is:
For a set of points on a plane P we separate them with a vertical line A, such that subsets P_L and P_R have the same number of points from P (points might be on that line A). Then, we make an array of these points X (sorted by x-coordinate), and build arrays X_L, X_R that contain points from subsets P_L and P_R respectively. We do the same with an array of these points Y (sorted by y-coordinate) and build arrays Y_L, Y_R.
As I understand, the separation line A doesn't depend on the way we sort points on the plane, so X_L will have the same amount of points as Y_L, and X_R as Y_R. The only difference between, say, X_L and Y_R is the order of the points in them. So I make the partition according to my understanding and my program fails in some cases (I compare the output of this algorithm with a naive O(n^2) version).
Do I understand the partition procedure correctly or am I missing something?
The partition part of my code attached:
struct point {
int x;
int y;
}
double find_min_dist(vector<point>& xs, vector<point>& ys, int num_p) {
int mid;
point median;
double min_left, min_right, min_d;
//if there are less than 3 points, we find min_dist by bruteforce
if (num_p <= 3) {
return slow_closest(xs, num_p);
}
vector<point> y_left, y_right;
vector<point> x_left, x_right;
vector<point> y_trunc;
//find a place for partition
mid = num_p / 2;
if (2 * mid == num_p) {
median = xs[mid];
}
else {
mid = mid + 1;
median = xs[mid + 1];
}
//fill in X_L and X_R arrays
int y_li = 0;
for (auto i = 0; i < mid; ++i) {
x_left.push_back(xs[i]);
}
for (auto i = 0; i < num_p - mid; ++i) {
x_right.push_back(xs[mid + i]);
}
//fill in Y_L and Y_R arrays
for (auto i = 0; i < num_p; ++i) {
if (y_li < mid) {
y_left.push_back(ys[i]);
y_li++;
}
else if (y_li == mid) {
y_left.push_back(ys[i]);
y_right.push_back(ys[i]);
y_li++;
}
else {
y_right.push_back(ys[i]);
}
}
//place for other parts of the code, which are irrelevant for my question
I have a list of 'cell' objects in a 2d array of length [sizeX][sizeY]. These Cell objects contain an array of type *Cell, which should point to each of the given cell's adjacent cells in the format North, East, South, West (Never Eat Soggy Waffles).
This array is called compass, and is defined with a length of 4. After the cells have been initialized (at which time all values of compass are set to nullptr), I have a loop which attempts to fill Cell.compass with pointers to the appropriate nearby cells.
However, I have found that despite all this, in each cell I have found that compass still is full of null values.
In this loop, I also run a function Cell::computeTopology() which populates a vector (which is a property of Cell) of the valid non-null indexes of compass. This is similarly empty.
I have made a breakpoint both before and after this function has been called to the exact same effect. Regardless I will include this function as well. I'm utterly perplexed and some help here would be greatly appreciated.
Problem area:
const int sizeX = SCREEN_WIDTH / SCALE;
const int sizeY = SCREEN_HEIGHT / SCALE;
Cell cells[sizeX][sizeY];
for (int x = 0; x < sizeX; x++){
for (int y = 0; y < sizeY; y++){
cells[x][y].setPos(x, y);
cells[x][y] = Cell();
//cells[x][y].setColor(rand() % 255, rand() % 255, rand() % 255);
}
}
for (int x = 0; x < sizeX; x++) {
for (int y = 0; y < sizeY; y++) {
Cell c = cells[x][y];
if (x - 1 >= 0) {
c.compass[3] = &cells[x - 1][y];
}
if (x + 1 < (SCREEN_WIDTH / SCALE)) {
c.compass[1] = &cells[x + 1][y];
}
if (y - 1 >= 0) {
c.compass[0] = &cells[x][y - 1];
}
if (y + 1 < (SCREEN_HEIGHT / SCALE)) {
c.compass[2] = &cells[x][y + 1];
}
c.computeTopology();
}
}
And the computeTopology() function
void Cell::computeTopology()
{
int i = 0;
for (Cell *c : compass) {
if (c != nullptr) {
notNull.push_back(i);
i++;
}
}
}
Change
Cell c = cells[x][y]; // make a copy
to
Cell& c = cells[x][y];
you want to modify item of array, not copy.
Another issue
cells[x][y].setPos(x, y);
cells[x][y] = Cell(); // ?
you are setting some members of cells[x][y] by calling setPos and after it you are overwriting cells[x][y] by default constructed Cell object. I think the second line in above code should be removed.
Your words
which populates a vector (which is a property of Cell) of the valid
non-null indexes of compass
so i index should be advanced with every iteration of for loop:
int i = 0;
for (Cell *c : compass) {
if (c != nullptr) {
notNull.push_back(i);
}
++i; // moved
}
LIBIQTOOL_API void Hist(std::vector<double>input, std::vector<double> bins, std::vector<double>& histogram)
{
double minY = *std::min_element(std::begin(input), std::end(input));
double maxY = *std::max_element(std::begin(input), std::end(input));
std::vector<double> edges;
edges.push_back(-1 * std::numeric_limits<double>::infinity());
for (int i = 0; i < bins.size() - 1; i++)
{
edges.push_back(bins[i] + 0.0100 / 2);
}
edges.push_back(std::numeric_limits<double>::infinity());
//histC
histogram.resize(edges.size() - 1);
#pragma omp parallel for
for (int i = 0; i < input.size(); i++)
{
for (int j = 0; j < edges.size() - 1; j++)
{
if ((edges[j] < input[i]) && (input[i] <= edges[j + 1]))
{
histogram[j] = histogram[j] + 1;
break;
}
}
}
histogram[histogram.size() - 1] = histogram[histogram.size() - 1] + histogram[histogram.size() - 2];
histogram.pop_back();
}
the input vector is size 3,000,000++ and the number of bins is ~7000.
I have taken Matlab's Hist() function and created the code I need in c++.
however it take very long to run, can you see more optimizations for runtime which can be done here?
I did:
a. break when you find the bin to place the current number
b. use openMP
Possible optimizations:
do not pass your input data by value, but by const reference
Do not check lower bound, only upper bound for each bin when doing the linear search for the correct bin.
Alternatively: Since your bins are ordered monotonously and there are no gaps, do a binary search for the correct bin, not a linear search.
The last one should give you the greatest gains, the others are more trivial to implement.
Btw the way you fill the edges vector looks strange.
I am asked to create a unique (no two numbers are the same) set of random numbers
(the user inputs the row and column dimensions 'd1' and 'd2')
I am totally lost as to how to compare each element of both arrays to see if they're duplicates.
(Max is the largest value to be generated)
void RandomArray(IntArrayPtr* m, int d1, int d2, int max)
{
for (int i = 0; i < d1; i++)
{
for (int j = 0; j < d2; j++)
{
m[i][j] = (rand() % max + 1);
if (i > 0 && j > 0)
{
if (m[i][j] == m[i][j - 1] || m[i][j] == m[i-1][j])
{
m[i][j] = (rand() % max+ 1);
}
}
}
}
}
Store every value in C++ datastructure called unordered_set and check if the random value generated exists in this set or not.
Reference on how to use unordered_set: https://stackoverflow.com/a/24644253/3326925
PS: I'm not that good in C++ but can tell you to relate this with HashSet used in Java.
Another solution is generating a set of n random numbers, using something like numbers.add( n + random() ) where n is the last number added and random() is a random increment (different each time).
Once you have the set, you can use std::random_shuffle(...)on it. And add the elements 1 by 1 on the matrix.
The problem consists in calculate all possible end positions and how many combinations exist for each one.
Given a start position x=0, a length m of the track and a list of jumps. Return the number of possible ends for each position on the interval [-m/2,+m/2]. The jumps must be done in the same order as given but it could be done in negative or positive way.
For example:
L = 40
jumps = 10, 10
Solution:
-20 : 1 (-10, -10)
0 : 2 (-10,+10 & +10,-10)
20 : 1 (+10,+10)
(The output needed is only the pair "position : #combinations")
I did it with a simple recursion, and the result is OK.
But in large sets of data, the execution time is few minutes or hours.
I know that with dynamic programming I can have a solution in few seconds, but I don't know how can I apply dynamic in this case.
There's my actual recursive function:
void escriuPosibilitats(queue<int> q, map<int,int> &res, int posicio, int m) {
int salt = q.front();
q.pop();
if(esSaltValid(m,posicio,-salt)) {
int novaPosicio = posicio - salt;
if(q.empty()) {
res[novaPosicio]++;
} else {
escriuPosibilitats(q,res,novaPosicio,m);
}
}
if(esSaltValid(m,posicio,salt)) {
int novaPosicio = posicio + salt;
if(q.empty()) {
res[novaPosicio]++;
} else {
escriuPosibilitats(q,res,novaPosicio,m);
}
}
}
Where q is the queue of the remaining jumps.
Where res is the parcial solution.
Where posicio is the actual position.
Where m is the length of the track.
Where esSaltValid is a function that checks if the jump is valid in the range of the track length.
PD: Sorry for my english level. I tried to improve my question! Thanks =)
You can use the following idea. Let dp[x][i] be the number of ways to arrive to the position x using until the jump i. Then the answer would be dp[x][N] for each x, and where N is the number of jumps. Even more, you can realize that this dp depends only on the previous row, and then you can simply dp[x] and save the next row in some auxiliary array, and then replace it in each iteration. The code would be something like this:
const int MOD = (int)(1e8+7);
const int L = 100;
int N = 36;
int dx[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int dp[L+1];
int next[L+1];
int main() {
int shift = L/2; // to handle negative indexes
dp[shift] = 1; // the initial position has one way to arrive, since you start there
for (int i = 0; i < N; ++i) { // for each jump size
for (int x = -L/2; x <= L/2; ++x) { // for each possible position
if (-L/2 <= x + dx[i] && x + dx[i] <= L/2) // positive jump
next[x + shift] = (next[x + shift] + dp[x + dx[i] + shift]) % MOD;
if (-L/2 <= x - dx[i] && x - dx[i] <= L/2) // negative jump
next[x + shift] = (next[x + shift] + dp[x - dx[i] + shift]) % MOD;
}
for (int x = -L/2; x <= L/2; ++x) { // update current dp to next and clear next
dp[x+shift] = next[x+shift];
next[x+shift] = 0;
}
}
for (int x = -L/2; x <= L/2; ++x) // print the result
if (dp[x+shift] != 0) {
cout << x << ": " << dp[x+shift] << '\n';
}
}
Of course, in case L is too big to handle, you can compress the state space and save the results in a map, and not in an array. The complexity of the approach is O(L*N). Hope it helped.
EDIT: just compute everything modulo 1e8+7 and that's it.