#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 100000
typedef struct point_2d_s {
int x;
int y;
} point_2d_t;
void read_points(char *filename, int *n, point_2d_t points[N])
{
FILE *f = fopen(filename, "r");
if (!f) {
printf("fopen: no such file '%s'!\n", filename);
exit(1);
}
fscanf(f, "%d", n);
int i;
for (i = 0; i < *n; i++) {
fscanf(f, "%d %d", &points[i].x, &points[i].y);
}
fclose(f);
}
void print_points(point_2d_t *points, int n)
{
int i;
for (i = 0; i < n; i++)
printf("%d %d\n", points[i].x, points[i].y);
printf("\n");
}
point_2d_t *copy_points(point_2d_t *points, int n)
{
point_2d_t *points_copy = malloc(n * sizeof(point_2d_t));
int i;
for (i = 0; i < n; i++) {
points_copy[i].x = points[i].x;
points_copy[i].y = points[i].y;
}
return points_copy;
}
int compare_x(point_2d_t *a, point_2d_t *b)
{
if (a->x == b->x)
return compare_y(a, b);
if (a->x < b->x)
return -1;
if (a->x > b->x)
return 1;
}
int compare_y(point_2d_t *a, point_2d_t *b)
{
if (a->y == b->y)
return 0;
if (a->y < b->y)
return -1;
if (a->y > b->y)
return 1;
}
void merge_points(point_2d_t *points, int l, int m, int r, int (*compare_fct)(point_2d_t *, point_2d_t *))
{
int i = l, j = m + 1, k = 0;
point_2d_t sorted_points[N];
while (i <= m && j <= r)
if (compare_fct(&points[i], &points[j]) <= 0) {
sorted_points[k].x = points[i].x;
sorted_points[k].y = points[i].y;
k++;
i++;
} else {
sorted_points[k].x = points[j].x;
sorted_points[k].y = points[j].y;
k++;
j++;
}
while (i <= m) {
sorted_points[k].x = points[i].x;
sorted_points[k].y = points[i].y;
k++;
i++;
}
while (j <= r) {
sorted_points[k].x = points[j].x;
sorted_points[k].y = points[j].y;
k++;
j++;
}
for (i = l, k = 0; i <= r; i++) {
points[i].x = sorted_points[k].x;
points[i].y = sorted_points[k].y;
k++;
}
}
void sort_points(point_2d_t *points, int l, int r, int (*compare_fct)(point_2d_t *, point_2d_t *))
{
if (l < r) {
int m = (l + r) / 2;
sort_points(points, l, m, compare_fct);
sort_points(points, m + 1, r, compare_fct);
merge_points(points, l, m, r, compare_fct);
}
}
int equal_points(point_2d_t *a, point_2d_t *b)
{
if (a->x == b->x && a->y == b->y)
return 1;
return 0;
}
double dist(point_2d_t *a, point_2d_t *b)
{
return sqrt(pow(a->x - b->x, 2) + pow(a->y - b->y, 2));
}
double closest_split_pair_dist(point_2d_t *points_x, int n, int l, int m, int r, double delta)
{
int i;
double min_x = points_x[m].x - delta;
for (i = m; i >= l; i--)
if (points_x[i].x >= min_x)
continue;
else break;
i++;
int j;
double max_x = points_x[m].x + delta;
for (j = m + 1; j <= r; j++)
if (points_x[j].x <= max_x)
continue;
else
break;
j--;
double min_dist = delta;
int k1, k2;
for (k1 = i; k1 < j; k1++) {
for (k2 = k1 + 1; k2 <= j; k2++) {
double d = dist(&points_x[k1], &points_x[k2]);
if (d < min_dist)
min_dist = d;
}
}
return min_dist;
}
double closest_pair_dist(point_2d_t *points_x, int n, int l, int r)
{
if (r - l > 2) {
int m = (l + r) / 2;
double min_dist_left = closest_pair_dist(points_x, n ,l, m);
double min_dist_right = closest_pair_dist(points_x, n, m + 1, r);
double delta = min_dist_left < min_dist_right ? min_dist_left : min_dist_right;
double min_dist_split = closest_split_pair_dist(points_x, n, l, m, r, delta);
return delta < min_dist_split ? delta : min_dist_split;
} else if (r - l == 1) {
return dist(&points_x[l], &points_x[r]);
} else if (r - l == 2) {
double d1 = dist(&points_x[l], &points_x[l + 1]);
double d2 = dist(&points_x[l], &points_x[r]);
double d3 = dist(&points_x[l + 1], &points_x[r]);
double min_dist = d1 < d2 ? d1 : d2;
return d3 < min_dist ? d3 : min_dist;
}
}
int main(int argc, char **argv)
{
/*
if (argc != 2) {
printf("usage: ./closest_points_pair <input_file>\n");
exit(1);
}
*/
int n;
point_2d_t points[N];
read_points(/*argv[1]*/ "cmap.in", &n, points);
sort_points(points, 0, n - 1, compare_x);
// sort_points(points_copy, 0, n - 1, compare_y);
double min_dist = closest_pair_dist(points, n, 0, n - 1);
FILE *f = fopen("cmap.out", "w");
fprintf(f, "%f\n", min_dist);
fclose(f);
return 0;
}