#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <string.h>

#include <time.h>
#include <random>
#include <iomanip>
using namespace std;

#define ll long long
#define N 100005
#define M_PI 3.14159265358979323846
/*
 x^2 + y^2 = r^2

 (x-x0)^2 + (y-y0)^2 = r0^2

 x^2 -2*x*x0 + x0^2 + y^2 - 2*y*y0 + y0^2 = r0^2
 x0^2 + y0^2 - 2x*x0 - 2y*y0 = r0^2 - r^2

 -2y*y0 = (r0^2-r^2-x0^2-y0^2) + 2x*x0
 y = (-x0/y0)*x - (r0^2-r^2-x0^2-y0^2)/(2*y0)

 (x-x0)^2 + (y-y0)^2 = r0^2
 x^2 -2*x*x0 + x0^2 + y^2 - 2*y*y0 + y0^2 = r0^2

 */

ll xo, yo, v, T, r0, n;
ll xc[N], yc[N], rc[N];
double angS[N], angF[N];
bool b[N];

pair<pair<double, double>, pair<double, double> >  tangent(double x, double y, double r, double xp, double yp) {
    if (r == 0)
        return {{0, 0}, {0, 0}};

    //shift and scale
    xp = (xp-x)/r;
    yp = (yp-y)/r;

    double a, b, c;
    a = (xp*xp + yp*yp);
    b = -2*xp;
    c = 1-yp*yp;

    double xRes1 = ((-1*b)+sqrt(b*b-4*a*c))/(2*a);
    double yRes1 = (1-xRes1*xp)/yp;

    double xRes2 = ((-1*b)-sqrt(b*b-4*a*c))/(2*a);
    double yRes2 = (1-xRes2*xp)/yp;

    if (yp == 0) {
        yRes1 = -1*sqrt(1-xRes1*xRes1);
        yRes2 = sqrt(1-xRes2*xRes2);
    }

    //shift and scale back
    xRes1 = r*xRes1 + x;
    yRes1 = r*yRes1 + y;
    xRes2 = r*xRes2 + x;
    yRes2 = r*yRes2 + y;

    return {{xRes1, yRes1}, {xRes2, yRes2}};
}

pair<double, double> calc2(double x, double y, double r, double &dist) {
    pair<pair<double, double>, pair<double, double> > pp = tangent(x, y, r, 0.0, 0.0);

    //cout << "(" << pp.first.first << ", " << pp.first.second << "), (" << pp.second.first << ", " << pp.second.second << ")" << endl;

    double ang1, ang2;
    ang1 = atan2(pp.first.second, pp.first.first);
    ang2 = atan2(pp.second.second, pp.second.first);

    if (ang1 < 0)
        ang1 += 2*M_PI;
    if (ang2 < 0)
        ang2 += 2*M_PI;

    if (ang1 > ang2)
        swap(ang1, ang2);
    if (ang2 - ang1 >= M_PI)
        swap(ang1, ang2);
    //cout << ang1 << " " << ang2 << endl;

    dist = sqrt(pow(pp.second.second-pp.first.second, 2) + pow(pp.second.first-pp.first.first,2));
    return {ang1, ang2};
}

void calc() {
    for (ll i = 0; i < n; i++) {
       double constant = rc[i]*rc[i]-r0*r0-xc[i]*xc[i]-yc[i]*yc[i];
        double a, b, c;

        bool toFlip = !yc[i];

        if (toFlip)
            swap(xc[i], yc[i]);

        constant /= (2*yc[i]);
        a = 1 + (xc[i]*xc[i])/(yc[i]*yc[i]);
        b = -2*xc[i] + 2*(xc[i]/yc[i])*constant + 2*xc[i];
        c = xc[i]*xc[i] + constant*constant + 2*constant*yc[i] + yc[i]*yc[i] - rc[i]*rc[i];

        double det = b*b-4*a*c;

        if (det <= 0) {
            angS[i] = angF[i] = 0;
            continue;
        }

        double xRes1 = ((-1*b)+sqrt(b*b-4*a*c))/(2*a);
        double yRes1 = (-1*xc[i]/yc[i])*xRes1 - constant;

        double xRes2 = ((-1*b)-sqrt(b*b-4*a*c))/(2*a);
        double yRes2 = (-1*xc[i]/yc[i])*xRes2 - constant;

        if (toFlip) {
            swap(xRes1, yRes1);
            swap(xRes2, yRes2);
        }

        angS[i] = atan2(yRes1, xRes1);
        angF[i] = atan2(yRes2, xRes2);

        if (angS[i] < 0)
            angS[i] += 2*M_PI;
        if (angF[i] < 0)
            angF[i] += 2*M_PI;

        if (angS[i] > angF[i])
            swap(angS[i], angF[i]);
        if (angF[i] - angS[i] >= M_PI)
            swap(angS[i], angF[i]);

        double distOld = sqrt(pow(yRes2-yRes1,2)+pow(xRes2-xRes1,2));
        double distNew;
        pair<double, double> p = calc2(xc[i], yc[i], rc[i], distNew);

        if (p.second-p.first > angF[i]-angS[i]) {
            if (distNew < distOld) {
                swap(angF[i], p.second);
                swap(angS[i], p.first);
            }
        }

    }
}

void solve() {
    cin >> n;

    for (ll i = 0; i < n; i++) {
        cin >> xc[i] >> yc[i] >> rc[i];
        xc[i] -= xo;
        yc[i] -= yo;

        if (rc[i] >= sqrt(xc[i]*xc[i]+yc[i]+yc[i])) {
            cout << 1 << endl;
            return;
        }
    }

    calc();
    pair<pair<double, bool>, ll> ang[2*N];
    for (ll i = 0; i < n; i++) {
        ang[i] = {{angS[i], false}, i};
        //cout << angS[i] << " " << angF[i] << endl;
    }
    for (ll i = n; i < 2*n; i++) {
        ang[i] = {{angF[i-n], true}, i-n};
    }
    sort(ang, ang+2*n);

    ll count = 0;
    double total = 0;
    double last = ang[0].first.first;
    for (ll i = 0; i < 2*n; i++) {
        //cout << count << " " << ang[i].first.first << " " << ang[i].first.second << " " << ang[i].second << endl;
        if (count > 0) {
            total += ang[i].first.first-last;
            //cout << "counted " << ang[i].first.first-last << endl;
        }
        if (!ang[i].first.second) {
            count++;
            b[ang[i].second] = true;
        }
        else if (b[ang[i].second]) {
            count--;
        }
        last = ang[i].first.first;
    }
    if (count) {
        total += ang[0].first.first + 2*M_PI - last;
        //cout << "counted " << ang[0].first.first + 2*M_PI - last << endl;
    }
    cout << total/(2*M_PI) << endl;
}

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> xo >> yo >> v >> T;
    r0 = v*T;
    solve();
}


//
//  Created by Running Photon on 2016-06-16
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
#define longdouble double
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
const int maxv = 1e3 + 10;
const longdouble eps = 1e-12;
const longdouble PI = acos(-1);
int comp(longdouble x) {
    if(abs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}
struct Point {
    longdouble x, y;
    Point(longdouble _x = 0, longdouble _y = 0) : x(_x), y(_y) {}
    void read() {
        cin >> x >> y;
    }
    Point operator+ (Point rhs) {
        return Point(x + rhs.x, y + rhs.y);
    }
    Point operator- (Point rhs) {
        return Point(x - rhs.x, y - rhs.y);
    }
    Point operator* (longdouble rhs) {
        return Point(x * rhs, y * rhs);
    }
    Point operator/ (longdouble rhs) {
        return Point(x / rhs, y / rhs);
    }
    longdouble operator* (Point rhs) {
        return x * rhs.x + y * rhs.y;
    }
    longdouble operator^ (Point rhs) {
        return x * rhs.y - y * rhs.x;
    }
    longdouble dis() {
        return sqrt(x*x+y*y);
    }
};
struct Circle {
    Point o;
    longdouble r;
    void read() {
        o.read();
        cin >> r;
    }
    void print() {
        cout << o.x << ' ' << o.y << ' ' << r << endl;
    }
}c[maxn];
typedef pair <longdouble, longdouble> sta;
void add(vector <sta>& vec, longdouble st, longdouble ed) {
    while(st < -PI + eps) {
        st += PI * 2.0;
    }
    while(st > PI - eps) {
        st -= 2.0 * PI;
    }
    while(ed < -PI + eps) {
        ed += PI * 2.0;
    }
    while(ed > PI - eps) {
        ed -= 2.0 * PI;
    }
    if(st < ed) {
        vec.push_back(sta(st, ed));
    }
    else {
        vec.push_back(sta(st, PI));
        vec.push_back(sta(-PI, ed));
    }
}
int main() {
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
//	ios_base::sync_with_stdio(0);
    longdouble x, y, v, t;
    cin >> x >> y >> v >> t;
    Circle p;
    p.o.x = x;
    p.o.y = y;
    p.r = v * t;
    int n; cin >> n;
    for(int i = 1; i <= n; i++) {
        c[i].read();
    }
//    p.print();
    vector <sta> vec;
    int flag = 0;
    for(int i = 1; i <= n; i++) {
        longdouble dis = (c[i].o-p.o).dis();
        Point k = c[i].o - p.o;
        longdouble r1 = c[i].r;
        longdouble r2 = p.r;
//        cout << dis << ' ' << r2 << endl;
        if(dis <= r1) {
//                puts("debvyug");
            flag = 1;
            break;
        }
        if(comp(r1+r2-dis) <= 0) continue; ///相离或相切
        else if(comp(abs(r1-r2)-dis) >= 0) {    ///包含
            longdouble ang = atan2(k.y, k.x);
            longdouble a = asin(r1/dis);
            longdouble st = ang - a;
            longdouble ed = ang + a;
            add(vec, st, ed);
        }
        else {
            if(dis > r1 + eps) {
                longdouble rk = sqrt(dis*dis - r1*r1);
                if(rk <= r2) {
                    longdouble ang = atan2(k.y, k.x);
                    longdouble a = asin(r1/dis);
                    longdouble st = ang - a;
                    longdouble ed = ang + a;
                    add(vec, st, ed);
                    continue;
                }
            }
            longdouble a = acos((r2*r2+dis*dis-r1*r1) / (2.0*dis*r2));
            longdouble ang = atan2(k.y, k.x);
            longdouble st = ang - a;
            longdouble ed = ang + a;
            add(vec, st, ed);
        }
    }
    if(flag) puts("1.0");
    else {
        sort(ALL(vec));
        longdouble res = 0;
        longdouble st = 0, ed = 0;
        if(vec.size()) {
            st = vec[0].first;
            ed = vec[0].second;
        }
//        cout << vec.size() << endl;
//        cout << st << ' ' << ed << endl;
        for(int i = 1; i < vec.size(); i++) {
//            cout << vec[i].first << ' ' << vec[i].second << endl;
            if(vec[i].first <= ed) ed = max(ed, vec[i].second);
            else {
                res += ed - st;
                st = vec[i].first;
                ed = vec[i].second;
            }
//            cout << res << endl;
        }
        res += ed - st;
//        cout << res << endl;
        cout << res / (2.0 * PI) << endl;
    }
	return 0;
}

/*
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         佛祖保佑       永无BUG
*/


//
//  Created by Running Photon on 2016-06-16
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;
const double PI = acos(-1);
int comp(double x) {
    if(abs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}
struct Point {
    double x, y;
    Point(double _x = 0, double _y = 0) : x(_x), y(_y) {}
    void read() {
        scanf("%lf%lf", &x, &y);
    }
    Point operator+ (Point rhs) {
        return Point(x + rhs.x, y + rhs.y);
    }
    Point operator- (Point rhs) {
        return Point(x - rhs.x, y - rhs.y);
    }
    Point operator* (double rhs) {
        return Point(x * rhs, y * rhs);
    }
    Point operator/ (double rhs) {
        return Point(x / rhs, y / rhs);
    }
    double operator* (Point rhs) {
        return x * rhs.x + y * rhs.y;
    }
    double operator^ (Point rhs) {
        return x * rhs.y - y * rhs.x;
    }
    double dis() {
        return sqrt(x*x+y*y);
    }
};
struct Circle {
    Point o;
    double r;
    void read() {
        o.read();
        scanf("%lf", &r);
    }
    void print() {
        printf("%f  %f  %f\n", o.x, o.y, r);
    }
}c[maxn];
typedef pair <double, double> sta;
void add(vector <sta>& vec, double st, double ed) {
    while(st < -PI + eps) {
        st += PI * 2.0;
    }
    while(st > PI - eps) {
        st -= 2.0 * PI;
    }
    while(ed < -PI + eps) {
        ed += PI * 2.0;
    }
    while(ed > PI - eps) {
        ed -= 2.0 * PI;
    }
    if(st < ed) {
        vec.push_back(sta(st, ed));
    }
    else {
        vec.push_back(sta(st, PI));
        vec.push_back(sta(-PI, ed));
    }
}
int main() {
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
//	ios_base::sync_with_stdio(0);
    double x, y, v, t;
    scanf("%lf%lf%lf%lf", &x, &y, &v, &t);
    Circle p;
    p.o.x = x;
    p.o.y = y;
    p.r = v * t;
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        c[i].read();
    }
//    p.print();
    vector <sta> vec;
    int flag = 0;
    for(int i = 1; i <= n; i++) {
        double dis = (c[i].o-p.o).dis();
        Point k = c[i].o - p.o;
        double r1 = c[i].r;
        double r2 = p.r;
        if(dis <= r1) {
            flag = 1;
//            puts("debug");
            break;
        }
        if(comp(r1+r2-dis) <= 0) continue;
        else if(comp(abs(r1-r2)-dis) >= 0) {
            double ang = atan2(k.y, k.x);
            double a = asin(r1/dis);
            double st = ang - a;
            double ed = ang + a;
            add(vec, st, ed);
        }
        else {
            if(dis > r1 + eps) {
                double rk = sqrt(dis*dis - r1*r1);
                if(rk <= r2) {
                    double ang = atan2(k.y, k.x);
                    double a = asin(r1/dis);
                    double st = ang - a;
                    double ed = ang + a;
                    add(vec, st, ed);
                    continue;
                }
            }
            double a = acos((r2*r2+dis*dis-r1*r1) / (2.0*dis*r2));
            double ang = atan2(k.y, k.x);
            double st = ang - a;
            double ed = ang + a;
            add(vec, st, ed);
        }
    }
    if(flag) puts("1.0000");
    else {
        sort(ALL(vec));
        double res = 0;
        double st = 0, ed = 0;
        if(vec.size()) {
            st = vec[0].first;
            ed = vec[0].second;
        }
//        cout << vec.size() << endl;
//        cout << st << ' ' << ed << endl;
        for(int i = 1; i < vec.size(); i++) {
//            cout << vec[i].first << ' ' << vec[i].second << endl;
            if(vec[i].first <= ed) ed = max(ed, vec[i].second);
            else {
                res += ed - st;
                st = vec[i].first;
                ed = vec[i].second;
            }
//            cout << res << endl;
        }
        res += ed - st;
//        cout << res << endl;
        printf("%.4f\n", res / 2.0 / PI);
    }
	return 0;
}

/*
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         佛祖保佑       永无BUG
*/


//
//  Created by Running Photon on 2016-06-16
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;
const double PI = acos(-1);
int comp(double x) {
    if(abs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}
struct Point {
    double x, y;
    Point(double _x = 0, double _y = 0) : x(_x), y(_y) {}
    void read() {
        scanf("%lf%lf", &x, &y);
    }
    Point operator+ (Point rhs) {
        return Point(x + rhs.x, y + rhs.y);
    }
    Point operator- (Point rhs) {
        return Point(x - rhs.x, y - rhs.y);
    }
    Point operator* (double rhs) {
        return Point(x * rhs, y * rhs);
    }
    Point operator/ (double rhs) {
        return Point(x / rhs, y / rhs);
    }
    double operator* (Point rhs) {
        return x * rhs.x + y * rhs.y;
    }
    double operator^ (Point rhs) {
        return x * rhs.y - y * rhs.x;
    }
    double dis() {
        return sqrt(x*x+y*y);
    }
};
struct Circle {
    Point o;
    double r;
    void read() {
        o.read();
        scanf("%lf", &r);
    }
    void print() {
        printf("%f  %f  %f\n", o.x, o.y, r);
    }
}c[maxn];
typedef pair <double, double> sta;
void add(vector <sta>& vec, double st, double ed) {
    while(st < -PI + eps) {
        st += PI * 2.0;
    }
    while(st > PI - eps) {
        st -= 2.0 * PI;
    }
    while(ed < -PI + eps) {
        ed += PI * 2.0;
    }
    while(ed > PI - eps) {
        ed -= 2.0 * PI;
    }
    if(st < ed) {
        vec.push_back(sta(st, ed));
    }
    else {
        vec.push_back(sta(st, PI));
        vec.push_back(sta(-PI, ed));
    }
}
int main() {
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
//	ios_base::sync_with_stdio(0);
    double x, y, v, t;
    scanf("%lf%lf%lf%lf", &x, &y, &v, &t);
    Circle p;
    p.o.x = x;
    p.o.y = y;
    p.r = v * t;
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        c[i].read();
    }
//    p.print();
    vector <sta> vec;
    int flag = 0;
    for(int i = 1; i <= n; i++) {
        double dis = (c[i].o-p.o).dis();
        Point k = c[i].o - p.o;
        double r1 = c[i].r;
        double r2 = p.r;
        if(dis <= r1) {
            flag = 1;
            break;
        }
        if(comp(r1+r2-dis) < 0) continue;
        else if(comp(abs(r1-r2)-dis) >= 0) {
            double ang = atan2(k.y, k.x);
            double a = asin(r1/dis);
            double st = ang - a;
            double ed = ang + a;
            add(vec, st, ed);
        }
        else {
            if(dis > r1 + eps) {
                double rk = sqrt(dis*dis - r1*r1);
                if(rk <= r2) {
                    double ang = atan2(k.y, k.x);
                    double a = asin(r1/dis);
                    double st = ang - a;
                    double ed = ang + a;
                    add(vec, st, ed);
                    continue;
                }
            }
            double a = acos((r2*r2+dis*dis-r1*r1) / (2.0*dis*r2));
            double ang = atan2(k.y, k.x);
            double st = ang - a;
            double ed = ang + a;
            add(vec, st, ed);
        }
    }
    if(flag) puts("1.0000");
    else {
        sort(ALL(vec));
        double res = 0;
        double st = 0, ed = 0;
        if(vec.size()) {
            st = vec[0].first;
            ed = vec[0].second;
        }
//        cout << vec.size() << endl;
//        cout << st << ' ' << ed << endl;
        for(int i = 1; i < vec.size(); i++) {
//            cout << vec[i].first << ' ' << vec[i].second << endl;
            if(vec[i].first <= ed) ed = max(ed, vec[i].second);
            else {
                res += ed - st;
                st = vec[i].first;
                ed = vec[i].second;
            }
//            cout << res << endl;
        }
        res += ed - st;
//        cout << res << endl;
        printf("%.4f\n", res / 2.0 / PI);
    }
	return 0;
}

/*
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         佛祖保佑       永无BUG
*/


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
int id;
    pt(int x, int y) : x(x), y(y) {}
};

double dd[3005][3005];

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
if (dd[p1.id][p2.id] > 0)
return dd[p1.id][p2.id];
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
dd[p1.id][p2.id] = sqrt(dx*dx+dy*dy);
    return dd[p1.id][p2.id];
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        sort (a.begin(), a.end(), &cmp);
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        pt p11(p1.x - p.x, p1.y - p.y);
        pt p22(p2.x - p.x, p2.y - p.y);
    double A = p22.y - p11.y;
    double B = p11.x - p22.x;
        double C = -A * p11.x - B * p11.y;
        double x = -A * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        double y = -B * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        if (x >= min(p11.x, p22.x) && x <= max(p11.x, p22.x))
                if (y >= min(p11.y, p22.y) && y <= max(p11.y, p22.y))
                        res = min(res, sqrt(x * x + y * y));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
for (int i = 0; i <n ; i++)
for (int j = 0;j < n; j++)
dd[i][j] = -1;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
pp.id=i;
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 1.5;
        for (int it = 0; it < 35; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

int dist(pt p1, pt p2) {
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;
    return dx*dx+dy*dy;
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

int maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int n = need.size();
        int curBestId = 0;
		int bestDist = 0;
int ans = 0;
		for (int i = 0; i < n; i++) {
			bestDist = dist(need[i], need[curBestId]);
			while (true) {
				int next = (curBestId + 1);
				if (next == n)
					next = 0;
				int dd = dist(need[i], need[next]);
				if (dd >= bestDist) {
					bestDist = dd;
					curBestId = next;
				} else {
					break;
				}
			}
			if (bestDist > ans)
				ans = bestDist;
		}
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
bool debug=false;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
if (a[0].x == 5808)
debug = true;
        sort(a.begin(), a.end(), cmp);
        int l = 0, r = 1000000000;
        while (r - l > 1) {
                int m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= m)
                                        allOk.push_back(a[i]);
                        int dmax = maxDist(allOk);
                        if (dmax >= m) {
                                ok = true;
if (debug) printf("%d - %d\n", first, dmax );
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
if (debug) printf("%d %d\n", l, r);
        }
        printf("%.10f\n", sqrt(l) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    return sqrt(dx*dx+dy*dy);
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 1.5;
        for (int it = 0; it < 35; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
int id;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
if (dist[p1.id][p2.id] > 0)
return dist[p1.id][p2.id];
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
dist[p1.id][p2.id] = sqrt(dx*dx+dy*dy);
    return dist[p1.id][p2.id];
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        sort (a.begin(), a.end(), &cmp);
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        pt p11(p1.x - p.x, p1.y - p.y);
        pt p22(p2.x - p.x, p2.y - p.y);
    double A = p22.y - p11.y;
    double B = p11.x - p22.x;
        double C = -A * p11.x - B * p11.y;
        double x = -A * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        double y = -B * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        if (x >= min(p11.x, p22.x) && x <= max(p11.x, p22.x))
                if (y >= min(p11.y, p22.y) && y <= max(p11.y, p22.y))
                        res = min(res, sqrt(x * x + y * y));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

double dist[3005][3005];

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
for (int i = 0; i <n ; i++)
for (int j = 0;j < n; j++)
dist[i][j] = -1;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
pp.id=i;
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 1.5;
        for (int it = 0; it < 35; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

int dist(pt p1, pt p2) {
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;
    return dx*dx+dy*dy;
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

int maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int n = need.size();
        int curBestId = 0;
		int bestDist = 0;
int ans = 0;
		for (int i = 0; i < n; i++) {
			bestDist = dist(need[i], need[curBestId]);
			while (true) {
				int next = (curBestId + 1);
				if (next == n)
					next = 0;
				double dd = dist(need[i], need[next]);
				if (dd >= bestDist) {
					bestDist = dd;
					curBestId = next;
				} else {
					break;
				}
			}
			if (bestDist > ans)
				ans = bestDist;
		}
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
bool bebug=false;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
if (a[0].x == 5808)
debug = true;
        sort(a.begin(), a.end(), cmp);
        int l = 0, r = 1000000000;
        while (r - l > 1) {
                int m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= m)
                                        allOk.push_back(a[i]);
                        int dmax = maxDist(allOk);
                        if (dmax >= m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
if (debug) printf("%d %d\n", l, r);
        }
        printf("%.10f\n", sqrt(l) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    return sqrt(dx*dx+dy*dy);
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int n = need.size();
        int curBestId = 0;
		double bestDist = 0;
double ans = 0;
		for (int i = 0; i < n; i++) {
			bestDist = dist(need[i], need[curBestId]);
			while (true) {
				int next = (curBestId + 1);
				if (next == n)
					next = 0;
				double dd = dist(need[i], need[next]);
				if (dd >= bestDist) {
					bestDist = dd;
					curBestId = next;
				} else {
					break;
				}
			}
			if (bestDist > ans)
				ans = bestDist;
		}
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 1.5;
        for (int it = 0; it < 35; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;

#define For(i,n) for(int i=0; i<(n); i++)
#define mp(a,b) make_pair((a),(b))
typedef int ll;
typedef pair<int,int> pii;

int n;

ll vzd(pii a, pii b){
    return (ll)(a.first-b.first)*(a.first-b.first)+(ll)(a.second-b.second)*(a.second-b.second);
}

pii vect(pii a, pii b) {
    return mp(b.first-a.first,b.second-a.second);
}

ll cross(pii a, pii b) {
    return (ll)a.first*b.second-(ll)a.second*b.first;
}

int sgn(ll a) {
    if(a>0) return 1;
    if(a<0) return -1;
    return 0;
}

int main() {
    vector<pii> A;
    scanf("%d",&n);
    For(i,n) {
        int x,y;
        scanf(" %d %d",&x,&y);
        A.push_back(mp(x,y));
    }
    ll z=0,k=21000*21000;
    sort(A.begin(),A.end());
    vector<pii> B;
    vector<pii> up,down;
    while(k-z>1) {
        ll stred=(z+k)/2;
        //if(k-z<0.000001) break;
        bool t=false;
        //pick first point
        for(int i=A.size()-1; i>=0; i--) {
            //pick distant points
            B.clear();
            For(j,n) if(vzd(A[i],A[j])>=stred) B.push_back(A[j]);
            //convex hull
            up.clear(); down.clear();
            For(j,B.size()) {
                if(up.size()<2) {up.push_back(B[j]); continue;}
                while(up.size()>1 && sgn(cross(vect(up[up.size()-2],up[up.size()-1]),vect(up[up.size()-2],B[j])))!=-1) up.pop_back();
                up.push_back(B[j]);
            }
            for(int j=B.size()-1; j>=0; j--) {
                if(down.size()<2) {down.push_back(B[j]); continue;}
                while(down.size()>1 && sgn(cross(vect(down[down.size()-2],down[down.size()-1]),vect(down[down.size()-2],B[j])))!=-1) down.pop_back();
                down.push_back(B[j]);
            }
            //find two distant points
            int kde=0;
            For(j,up.size()) {
                while(kde!=down.size()-1 && vzd(up[j],down[kde+1])>vzd(up[j],down[kde])) kde++;
                if(vzd(up[j],down[kde])>=stred) t=true;
                if(t) break;
            }
            if(t) break;
        }
        if(t) z=stred;
        else k=stred;
    }
    printf("%0.9lf\n",sqrt(z/4.0));
return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    return sqrt(dx*dx+dy*dy);
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        sort (a.begin(), a.end(), &cmp);
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        pt p11(p1.x - p.x, p1.y - p.y);
        pt p22(p2.x - p.x, p2.y - p.y);
    double A = p22.y - p11.y;
    double B = p11.x - p22.x;
        double C = -A * p11.x - B * p11.y;
        double x = -A * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        double y = -B * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        if (x >= min(p11.x, p22.x) && x <= max(p11.x, p22.x))
                if (y >= min(p11.y, p22.y) && y <= max(p11.y, p22.y))
                        res = min(res, sqrt(x * x + y * y));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 1.5;
        for (int it = 0; it < 35; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <stack>
using namespace std;

#define For(i,n) for(int i=0; i<(n); i++)
#define mp(a,b) make_pair((a),(b))
typedef int ll;
typedef pair<int,int> pii;

int n;

ll vzd(pii a, pii b){
    return (ll)(a.first-b.first)*(a.first-b.first)+(ll)(a.second-b.second)*(a.second-b.second);
}

pii vect(pii a, pii b) {
    return mp(b.first-a.first,b.second-a.second);
}

ll cross(pii a, pii b) {
    return (ll)a.first*b.second-(ll)a.second*b.first;
}

int sgn(ll a) {
    if(a>0) return 1;
    if(a<0) return -1;
    return 0;
}

int main() {
    vector<pii> A;
    scanf("%d",&n);
    For(i,n) {
        int x,y;
        scanf(" %d %d",&x,&y);
        A.push_back(mp(x,y));
    }
    ll z=0,k=21000*21000;
    sort(A.begin(),A.end());
    vector<pii> B;
    vector<pii> up,down;
    while(k-z>1) {
        ll stred=(z+k)/2;
        //if(k-z<0.000001) break;
        bool t=false;
        //pick first point
        for(int i=A.size()-1; i>=0; i--) {
            //pick distant points
            B.clear();
            For(j,n) if(vzd(A[i],A[j])>=stred) B.push_back(A[j]);
            //convex hull
            up.clear(); down.clear();
            For(j,B.size()) {
                if(up.size()<2) {up.push_back(B[j]); continue;}
                while(up.size()>1 && sgn(cross(vect(up[up.size()-2],up[up.size()-1]),vect(up[up.size()-2],B[j])))!=-1) up.pop_back();
                up.push_back(B[j]);
            }
            for(int j=B.size()-1; j>=0; j--) {
                if(down.size()<2) {down.push_back(B[j]); continue;}
                while(down.size()>1 && sgn(cross(vect(down[down.size()-2],down[down.size()-1]),vect(down[down.size()-2],B[j])))!=-1) down.pop_back();
                down.push_back(B[j]);
            }
            //find two distant points
            int kde=0;
            For(j,up.size()) {
                while(kde!=down.size()-1 && vzd(up[j],down[kde+1])>vzd(up[j],down[kde])) kde++;
                if(vzd(up[j],down[kde])>=stred) t=true;
                if(t) break;
            }
            if(t) break;
        }
        if(t) z=stred;
        else k=stred;
    }
    printf("%0.9lf\n",sqrt(z/4.0));
return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    return sqrt(dx*dx+dy*dy);
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        sort (a.begin(), a.end(), &cmp);
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        pt p11(p1.x - p.x, p1.y - p.y);
        pt p22(p2.x - p.x, p2.y - p.y);
    double A = p22.y - p11.y;
    double B = p11.x - p22.x;
        double C = -A * p11.x - B * p11.y;
        double x = -A * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        double y = -B * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        if (x >= min(p11.x, p22.x) && x <= max(p11.x, p22.x))
                if (y >= min(p11.y, p22.y) && y <= max(p11.y, p22.y))
                        res = min(res, sqrt(x * x + y * y));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 2;
        for (int it = 0; it < 60; it++) {
        if (r - l < 1e-6)
            break;
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

int dist(pt p1, pt p2) {
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;
    return dx*dx+dy*dy;
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

int maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int n = need.size();
        int curBestId = 0;
		int bestDist = 0;
int ans = 0;
		for (int i = 0; i < n; i++) {
			bestDist = dist(need[i], need[curBestId]);
			while (true) {
				int next = (curBestId + 1);
				if (next == n)
					next = 0;
				double dd = dist(need[i], need[next]);
				if (dd >= bestDist) {
					bestDist = dd;
					curBestId = next;
				} else {
					break;
				}
			}
			if (bestDist > ans)
				ans = bestDist;
		}
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
bool debug=false;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
if (a[0].x == 5808)
debug = true;
        sort(a.begin(), a.end(), cmp);
        int l = 0, r = 1000000000;
        while (r - l > 1) {
                int m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= m)
                                        allOk.push_back(a[i]);
                        int dmax = maxDist(allOk);
                        if (dmax >= m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
if (debug) printf("%d %d\n", l, r);
        }
        printf("%.10f\n", sqrt(l) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    return sqrt(dx*dx+dy*dy);
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        sort (a.begin(), a.end(), &cmp);
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        pt p11(p1.x - p.x, p1.y - p.y);
        pt p22(p2.x - p.x, p2.y - p.y);
    double A = p22.y - p11.y;
    double B = p11.x - p22.x;
        double C = -A * p11.x - B * p11.y;
        double x = -A * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        double y = -B * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        if (x >= min(p11.x, p22.x) && x <= max(p11.x, p22.x))
                if (y >= min(p11.y, p22.y) && y <= max(p11.y, p22.y))
                        res = min(res, sqrt(x * x + y * y));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 2;
        for (int it = 0; it < 25; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

int dist(pt p1, pt p2) {
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;
    return dx*dx+dy*dy;
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

int maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int n = need.size();
        int curBestId = 0;
		int bestDist = 0;
int ans = 0;
		for (int i = 0; i < n; i++) {
			bestDist = dist(need[i], need[curBestId]);
			while (true) {
				int next = (curBestId + 1);
				if (next == n)
					next = 0;
				double dd = dist(need[i], need[next]);
				if (dd >= bestDist) {
					bestDist = dd;
					curBestId = next;
				} else {
					break;
				}
			}
			if (bestDist > ans)
				ans = bestDist;
		}
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        int l = 0, r = 1000000000;
        while (r - l > 1) {
                int m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= m)
                                        allOk.push_back(a[i]);
                        int dmax = maxDist(allOk);
                        if (dmax >= m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", sqrt(l) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool debug;

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

int dist(pt p1, pt p2) {
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;
    return dx*dx+dy*dy;
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

int maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
if (debug) printf("%d ", need.size());
        int n = need.size();
        int curBestId = 0;
		int bestDist = 0;
int ans = 0;
		for (int i = 0; i < n; i++) {
			bestDist = dist(need[i], need[curBestId]);
			while (true) {
				int next = (curBestId + 1);
				if (next == n)
					next = 0;
				double dd = dist(need[i], need[next]);
				if (dd >= bestDist) {
					bestDist = dd;
					curBestId = next;
				} else {
					break;
				}
			}
			if (bestDist > ans)
				ans = bestDist;
		}
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
debug=false;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
if (a[0].x == 5808)
debug = true;
        sort(a.begin(), a.end(), cmp);
        int l = 0, r = 1000000000;
        while (r - l > 1) {
                int m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= m)
                                        allOk.push_back(a[i]);
                        int dmax = maxDist(allOk);
                        if (dmax >= m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
if (debug) printf("%d %d\n", l, r);
        }
        printf("%.10f\n", sqrt(l) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    return sqrt(dx*dx+dy*dy);
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        sort (a.begin(), a.end(), &cmp);
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        pt p11(p1.x - p.x, p1.y - p.y);
        pt p22(p2.x - p.x, p2.y - p.y);
    double A = p22.y - p11.y;
    double B = p11.x - p22.x;
        double C = -A * p11.x - B * p11.y;
        double x = -A * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        double y = -B * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        if (x >= min(p11.x, p22.x) && x <= max(p11.x, p22.x))
                if (y >= min(p11.y, p22.y) && y <= max(p11.y, p22.y))
                        res = min(res, sqrt(x * x + y * y));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 2;
        for (int it = 0; it < 30; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

int dist(pt p1, pt p2) {
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;
    return dx*dx+dy*dy;
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

int maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
if (debug) printf("%d ", need.size());
        int n = need.size();
        int curBestId = 0;
		int bestDist = 0;
int ans = 0;
		for (int i = 0; i < n; i++) {
			bestDist = dist(need[i], need[curBestId]);
			while (true) {
				int next = (curBestId + 1);
				if (next == n)
					next = 0;
				double dd = dist(need[i], need[next]);
				if (dd >= bestDist) {
					bestDist = dd;
					curBestId = next;
				} else {
					break;
				}
			}
			if (bestDist > ans)
				ans = bestDist;
		}
        return ans;
}

bool debug;

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
debug=false;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
if (a[0].x == 5808)
debug = true;
        sort(a.begin(), a.end(), cmp);
        int l = 0, r = 1000000000;
        while (r - l > 1) {
                int m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= m)
                                        allOk.push_back(a[i]);
                        int dmax = maxDist(allOk);
                        if (dmax >= m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
if (debug) printf("%d %d\n", l, r);
        }
        printf("%.10f\n", sqrt(l) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
int id;
    pt(int x, int y) : x(x), y(y) {}
};

double dist[3005][3005];

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
if (dist[p1.id][p2.id] > 0)
return dist[p1.id][p2.id];
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
dist[p1.id][p2.id] = sqrt(dx*dx+dy*dy);
    return dist[p1.id][p2.id];
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        sort (a.begin(), a.end(), &cmp);
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        pt p11(p1.x - p.x, p1.y - p.y);
        pt p22(p2.x - p.x, p2.y - p.y);
    double A = p22.y - p11.y;
    double B = p11.x - p22.x;
        double C = -A * p11.x - B * p11.y;
        double x = -A * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        double y = -B * 1. * C / sqrt(A * 1. * A + B * 1 * B);
        if (x >= min(p11.x, p22.x) && x <= max(p11.x, p22.x))
                if (y >= min(p11.y, p22.y) && y <= max(p11.y, p22.y))
                        res = min(res, sqrt(x * x + y * y));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
for (int i = 0; i <n ; i++)
for (int j = 0;j < n; j++)
dist[i][j] = -1;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
pp.id=i;
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 1.5;
        for (int it = 0; it < 35; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
int id;
    pt(int x, int y) : x(x), y(y) {}
};

double dd[3005][3005];

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
if (dd[p1.id][p2.id] > 0)
return dd[p1.id][p2.id];
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
dd[p1.id][p2.id] = sqrt(dx*dx+dy*dy);
    return dd[p1.id][p2.id];
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        sort (a.begin(), a.end(), &cmp);
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int A = 0;
        int B = 0;
        int n = need.size();
        double curD = getDistFromVertexToEdge(need[B], need[A],
                                need[(A + 1) % n]);
        while (true) {
                double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                need[A], need[(A + 1) % n]);
                if (dd > curD) {
                        curD = dd;
                        B = (B + 1) % n;
                } else {
                        break;
                }
        }
        double ans = 0;
        for (int i = 0; i < n - 1; i++) {
                A++;
                if (A == n)
                        A = 0;
                while (true) {
                        double dd = getDistFromVertexToEdge(need[(B + 1) % n],
                                        need[A], need[(A + 1) % n]);
                        if (dd > curD) {
                                curD = dd;
                                B = (B + 1) % n;
                        } else {
                                break;
                        }
                }
                ans = max(ans, dist(need[A], need[B]));
                ans = max(ans, dist(need[(A + 1) % n], need[B]));
        }
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
for (int i = 0; i <n ; i++)
for (int j = 0;j < n; j++)
dd[i][j] = -1;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
pp.id=i;
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 1.5;
        for (int it = 0; it < 35; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <stack>
using namespace std;

#define For(i,n) for(int i=0; i<(n); i++)
#define mp(a,b) make_pair((a),(b))
typedef long long ll;
typedef pair<int,int> pii;

int n;

ll vzd(pii a, pii b){
    return (ll)(a.first-b.first)*(a.first-b.first)+(ll)(a.second-b.second)*(a.second-b.second);
}

pii vect(pii a, pii b) {
    return mp(b.first-a.first,b.second-a.second);
}

ll cross(pii a, pii b) {
    return (ll)a.first*b.second-(ll)a.second*b.first;
}

int sgn(ll a) {
    if(a>0) return 1;
    if(a<0) return -1;
    return 0;
}

int main() {
    vector<pii> A;
    scanf("%d",&n);
    For(i,n) {
        int x,y;
        scanf(" %d %d",&x,&y);
        A.push_back(mp(x,y));
    }
    ll z=0,k=21000*21000;
    sort(A.begin(),A.end());
    vector<pii> B;
    vector<pii> up,down;
    while(k-z>1) {
        ll stred=(z+k)/2;
        //if(k-z<0.000001) break;
        bool t=false;
        //pick first point
        for(int i=A.size()-1; i>=0; i--) {
            //pick distant points
            B.clear();
            For(j,n) if(vzd(A[i],A[j])>=stred) B.push_back(A[j]);
            //convex hull
            up.clear(); down.clear();
            For(j,B.size()) {
                if(up.size()<2) {up.push_back(B[j]); continue;}
                while(up.size()>1 && sgn(cross(vect(up[up.size()-2],up[up.size()-1]),vect(up[up.size()-2],B[j])))!=-1) up.pop_back();
                up.push_back(B[j]);
            }
            for(int j=B.size()-1; j>=0; j--) {
                if(down.size()<2) {down.push_back(B[j]); continue;}
                while(down.size()>1 && sgn(cross(vect(down[down.size()-2],down[down.size()-1]),vect(down[down.size()-2],B[j])))!=-1) down.pop_back();
                down.push_back(B[j]);
            }
            //find two distant points
            int kde=0;
            For(j,up.size()) {
                while(kde!=down.size()-1 && vzd(up[j],down[kde+1])>vzd(up[j],down[kde])) kde++;
                if(vzd(up[j],down[kde])>=stred) t=true;
                if(t) break;
            }
            if(t) break;
        }
        if(t) z=stred;
        else k=stred;
    }
    printf("%0.9lf\n",sqrt(z/4.0));
return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

struct pt {
    int x, y;
    pt(int x, int y) : x(x), y(y) {}
};

bool cmp (pt a, pt b) {
        return a.x < b.x || a.x == b.x && a.y < b.y;
}

bool cw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) < 0;
}

bool ccw (pt a, pt b, pt c) {
        return a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y) > 0;
}

double dist(pt p1, pt p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    return sqrt(dx*dx+dy*dy);
}

void getConvexHull (vector<pt> & a) {
    if (a.size() == 1)  return;
        pt p1 = a[0],  p2 = a.back();
        vector<pt> up, down;
        up.push_back (p1);
        down.push_back (p1);
        for (size_t i=1; i<a.size(); ++i) {
                if (i==a.size()-1 || cw (p1, a[i], p2)) {
                        while (up.size()>=2 && !cw (up[up.size()-2], up[up.size()-1], a[i]))
                                up.pop_back();
                        up.push_back (a[i]);
                }
                if (i==a.size()-1 || ccw (p1, a[i], p2)) {
                        while (down.size()>=2 && !ccw (down[down.size()-2], down[down.size()-1], a[i]))
                                down.pop_back();
                        down.push_back (a[i]);
                }
        }
        a.clear();
        for (size_t i=0; i<up.size(); ++i)
                a.push_back (up[i]);
        for (size_t i=down.size()-2; i>0; --i)
                a.push_back (down[i]);
}

double getDistFromVertexToEdge(pt p, pt p1, pt p2) {
        double res = min(dist(p, p1), dist(p, p2));
        return res;
}

double maxDist(vector<pt> & need) {
        if (need.size() <= 1)
                return 0;
        getConvexHull(need);
        int n = need.size();
        int curBestId = 0;
		double bestDist = 0;
		for (int i = 0; i < n; i++) {
			bestDist = dist(need[i], need[curBestId]);
			while (true) {
				int next = (curBestId + 1);
				if (next == n)
					next = 0;
				double dd = dist(need[i], need[next]);
				if (dd >= bestDist) {
					bestDist = dd;
					curBestId = next;
				} else {
					break;
				}
			}
			if (bestDist > ans)
				ans = bestDist;
		}
        return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pt> a;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        pt pp(x, y);
        a.push_back(pp);
    }
        sort(a.begin(), a.end(), cmp);
        double l = 0, r = 1e4 * 1.5;
        for (int it = 0; it < 35; it++) {
                double m = (l + r) / 2;
                bool ok = false;
                for (int first = 0; first < n; first++) {
                        vector<pt> allOk;
                        for (int i = 0; i < n; i++)
                                if (dist(a[first], a[i]) >= 2 * m)
                                        allOk.push_back(a[i]);
                        double dmax = maxDist(allOk);
                        if (dmax >= 2 * m) {
                                ok = true;
                                break;
                        }
                }
                if (ok) {
                        l = m;
                } else {
                        r = m;
                }
        }
        printf("%.10f\n", (l + r) / 2);
}


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <bitset>
#include <algorithm>
using namespace std;

int n,i,j,k,loop;
int x[3005],y[3005],d[3005],id[3005];
double dist[3005][3005],l,r,mid;
bitset<3005> f[3005],g;

double sqr(double x){return x*x;}
inline bool cmp(const int &a,const int &b){return d[a]>d[b];}

int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;++i)scanf("%d%d",&x[i],&y[i]);
	for(i=1;i<=n;++i)
	for(j=1;j<=n;++j)
	if(i==j)dist[i][j]=-100000;
	else dist[i][j]=sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
	g.reset();
	for(i=1;i<=n;++i)id[i]=i;
	l=0;r=50000;
	for(loop=30;loop;--loop)
	{
		mid=(l+r)/2;
		for(i=1;i<=n;++i)d[i]=0;
		for(i=1;i<=n;++i)
		for(j=1;j<=n;++j)
		if(dist[i][j]>=mid)
		{
			f[i][j]=1;
			++d[i];
		}else f[i][j]=0;
		sort(id+1,id+n+1,cmp);
		for(i=1;i<=n;++i)
		{
			for(j=1;j<=n;++j)
			if(f[id[i]][id[j]])
			if((f[id[i]]&f[id[j]])!=g)
			break;
			if(j<=n)break;
		}
		if(i<=n)l=mid;
		else r=mid;
	}
	printf("%.20lf\n",mid/2);
}


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <bitset>
#include <algorithm>
using namespace std;

int n,i,j,k,loop,q,w,e;
int x[3005],y[3005],d[3005],id[3005];
double dist[3005][3005],l,r,mid,tmp;
bitset<3005> f[3005],g;

double sqr(double x){return x*x;}
inline bool cmp(const int &a,const int &b){return d[a]>d[b];}

int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;++i)scanf("%d%d",&x[i],&y[i]);
	for(i=1;i<=n;++i)
	for(j=1;j<=n;++j)
	if(i==j)dist[i][j]=-100000;
	else dist[i][j]=sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
	for(loop=10000;loop;--loop)
	{
		q=rand()%n+1;
		for(w=rand()%n+1;w==q;w=rand()%n+1);
		for(e=rand()%n+1;e==q||e==w;e=rand()%n+1);
		tmp=min(dist[q][w],min(dist[q][e],dist[w][e]));
	}
	g.reset();
	for(i=1;i<=n;++i)id[i]=i;
	l=tmp;
	for(i=1;i<=n;++i)
	for(j=1;j<=n;++j)
	if(dist[i][j]>r)r=dist[i][j];
	for(;r-l>1e-7;)
	{
		mid=(l+r)/2;
		for(i=1;i<=n;++i)d[i]=0;
		for(i=1;i<=n;++i)
		for(j=1;j<=n;++j)
		if(dist[i][j]>=mid)
		{
			f[i][j]=1;
			++d[i];
		}else f[i][j]=0;
		sort(id+1,id+n+1,cmp);
		for(i=1;i<=n;++i)
		{
			for(j=1;j<=n;++j)
			if(f[id[i]][id[j]])
			if((f[id[i]]&f[id[j]])!=g)
			break;
			if(j<=n)break;
		}
		if(i<=n)l=mid;
		else r=mid;
	}
	printf("%.20lf\n",mid/2);
}


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <bitset>
#include <algorithm>
using namespace std;

int n,i,j,k,loop,q,w,e;
int x[3005],y[3005],d[3005],id[3005];
double dist[3005][3005],l,r,mid,tmp;
bitset<3005> f[3005],g;

double sqr(double x){return x*x;}
inline bool cmp(const int &a,const int &b){return d[a]>d[b];}

int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;++i)scanf("%d%d",&x[i],&y[i]);
	for(i=1;i<=n;++i)
	for(j=1;j<=n;++j)
	if(i==j)dist[i][j]=-100000;
	else dist[i][j]=sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
	for(loop=10000;loop;--loop)
	{
		q=rand()%n+1;
		for(w=rand()%n+1;w==q;w=rand()%n+1);
		for(e=rand()%n+1;e==q||e==w;e=rand()%n+1);
		tmp=min(dist[q][w],min(dist[q][e],dist[w][e]));
		if(tmp>l)l=tmp;
	}
	g.reset();
	for(i=1;i<=n;++i)id[i]=i;
	for(i=1;i<=n;++i)
	for(j=1;j<=n;++j)
	if(dist[i][j]>r)r=dist[i][j];
	for(;r-l>1e-6;)
	{
		mid=(l+r)/2;
		for(i=1;i<=n;++i)d[i]=0;
		for(i=1;i<=n;++i)
		for(j=1;j<=n;++j)
		if(dist[i][j]>=mid)
		{
			f[i][j]=1;
			++d[i];
		}else f[i][j]=0;
		sort(id+1,id+n+1,cmp);
		for(i=1;i<=n;++i)
		{
			for(j=1;j<=n;++j)
			if(f[id[i]][id[j]])
			if((f[id[i]]&f[id[j]]).any())
			break;
			if(j<=n)break;
		}
		if(i<=n)l=mid;
		else r=mid;
	}
	printf("%.20lf\n",mid/2);
}