//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <map>
#include <cassert>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <queue>
#include <complex>
#include <stack>
#include <string>
#include <iomanip>
#include <set>
#include <ctime>
#include <fstream>
#include <list>
#define  inf  0XFFFFFFFFFFFFFFFll
#define  dinf 1e11
#define  N    6111
#define  M    44444
#define  mod  1000000007ll
#define  LL   long long
#define  ULL  unsigned long long
#define  us   unsigned short int
#define  eps  1e-12
#define  pi   acos(-1.0)
#define  REP(i,n)    for (int i=0; i<n; i++)
#define  REP1(i,n)   for (int i=1; i<=n; i++)
#define  FOR(i,l,r)    for (int i=l; i<r; i++)
#define  FOR1(i,l,r) for (int i=l; i<=r; i++)
#define  TXT1

using namespace std;

#ifdef TXT
ifstream fi("in.txt");
#define  cin  fi
#endif

using namespace std;

struct Complex{double x, y;Complex(double _x=0.0,double _y=0.0):x(_x),y(_y){}};
Complex operator + (Complex a,Complex b){return Complex(a.x+b.x,a.y+b.y);}
Complex operator - (Complex a,Complex b){return Complex(a.x-b.x,a.y-b.y);}
Complex operator * (Complex a,Complex b){return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}

struct Point {
    double x, y, angle;
    Point(double xx=0,double yy=0) {x=xx;y=yy;}
    friend bool operator < (Point a, Point b) {return a.angle<b.angle;}
    friend double dis(Point a, Point b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
};

struct Seg {
    int l, r;
    double lm;
} seg[N*4];
double len[N];
void buildtree(int l, int r, int now=1) {
    seg[now].l = l; seg[now].r = r;
    if (l == r) {
        seg[now].lm = len[r];
        return;
    }
    int mid = (l + r) / 2;
    buildtree(l, mid, now*2);
    buildtree(mid+1, r, now*2+1);
    seg[now].lm = max(seg[now*2].lm, seg[now*2+1].lm);
}
double query(int l, int r, int now=1) {
    if (l<=seg[now].l&&seg[now].r<=r)
        return seg[now].lm;
    int mid = (seg[now].l+seg[now].r)/2;
    double ans = 0.0;
    if (l<=mid)
        ans = max(ans, query(l, r, now*2));
    if (r > mid)
        ans = max(ans, query(l, r, now*2+1));
    return ans;
}

double getangle(double x, double y) {
    if (fabs(x) < eps) {
        if (y > 0)
            return pi / 2.0;
        else return 3.0*pi/2.0;
    }
    if (fabs(y) < eps) {
        if (x > 0)
            return 0.0;
        else return pi;
    }
    double s = fabs(y/(sqrt(x*x+y*y)));
    double ret = asin(s);
    if (x > eps && y > eps) return ret;
    if (x < -eps && y > eps) return pi - ret;
    if (x < -eps && y < -eps) return pi + ret;
    return 2.0*pi - ret;
}

double work(Point point[N], int n) {
    REP1(i, n) point[i].angle = getangle(point[i].x, point[i].y);
    sort(point+1, point+1+n);
    FOR1(i, n+1, n*2) {
        point[i] = point[i-n];
        point[i].angle += 2.0*pi;
    }
    REP1(i, n*2) len[i] = dis(Point(.0,.0), point[i]);
    int be = 1, en = 1;
    buildtree(1, n);
    double ans = 0.0;
    REP1(i, n) {
        double temp = len[i];
        while (point[en].angle - point[i].angle <= pi+eps)
            en++;
        while (point[be].angle - point[i].angle <= pi/3.0+eps)
            be++;
        int be1 = be, en1 = en;
        if (be > n && en > n)
            be -= n, en -= n;
        if (be<en && en <= n+1) {
            temp = min(temp, query(be, en-1));
            ans = max(ans, temp);
        }
        else if (be < en) {
            temp = min(temp, max(query(be, n), query(1, en-1-n)));
            ans = max(ans, temp);
        }
        be = be1, en = en1;
    }
    return ans / 2.0;
}
Point p1[N], p2[N];

int main()
{
    int n; scanf("%d", &n);
    REP(i, n) scanf("%lf%lf", &p1[i].x, &p1[i].y);
    double ans = 0.0;
    REP(i, n) {
        int cnt = 0;
        REP(j, n) {
            if (fabs(p1[i].x-p1[j].x) <= eps && fabs(p1[i].y-p1[j].y) <= eps)
                continue;
            p2[++cnt].x = p1[j].x-p1[i].x;
            p2[cnt].y = p1[j].y-p1[i].y;
        }
        if (cnt >= 2)
            ans = max(ans, work(p2, cnt));
    }
    cout << fixed << setprecision(10) << ans << endl;
    return 0;
}


//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <map>
#include <cassert>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <queue>
#include <complex>
#include <stack>
#include <string>
#include <iomanip>
#include <set>
#include <ctime>
#include <fstream>
#include <list>
#define  inf  0XFFFFFFFFFFFFFFFll
#define  dinf 1e11
#define  N    6111
#define  M    44444
#define  mod  1000000007ll
#define  LL   long long
#define  ULL  unsigned long long
#define  us   unsigned short int
#define  eps  1e-12
#define  pi   acos(-1.0)
#define  REP(i,n)    for (int i=0; i<n; i++)
#define  REP1(i,n)   for (int i=1; i<=n; i++)
#define  FOR(i,l,r)    for (int i=l; i<r; i++)
#define  FOR1(i,l,r) for (int i=l; i<=r; i++)
#define  TXT1

using namespace std;

#ifdef TXT
ifstream fi("in.txt");
#define  cin  fi
#endif

using namespace std;

struct Complex{double x, y;Complex(double _x=0.0,double _y=0.0):x(_x),y(_y){}};
Complex operator + (Complex a,Complex b){return Complex(a.x+b.x,a.y+b.y);}
Complex operator - (Complex a,Complex b){return Complex(a.x-b.x,a.y-b.y);}
Complex operator * (Complex a,Complex b){return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}

struct Point {
    double x, y, angle;
    Point(double xx=0,double yy=0) {x=xx;y=yy;}
    friend bool operator < (Point a, Point b) {return a.angle<b.angle;}
    friend double dis(Point a, Point b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
};

struct Seg {
    int l, r;
    double lm;
} seg[N*4];
double len[N];
void buildtree(int l, int r, int now=1) {
    seg[now].l = l; seg[now].r = r;
    if (l == r) {
        seg[now].lm = len[r];
        return;
    }
    int mid = (l + r) / 2;
    buildtree(l, mid, now*2);
    buildtree(mid+1, r, now*2+1);
    seg[now].lm = max(seg[now*2].lm, seg[now*2+1].lm);
}
double query(int l, int r, int now=1) {
    if (l<=seg[now].l&&seg[now].r<=r)
        return seg[now].lm;
    int mid = (seg[now].l+seg[now].r)/2;
    double ans = 0.0;
    if (l<=mid)
        ans = max(ans, query(l, r, now*2));
    if (r > mid)
        ans = max(ans, query(l, r, now*2+1));
    return ans;
}

double getangle(double x, double y) {
    if (fabs(x) < eps) {
        if (y > 0)
            return pi / 2.0;
        else return 3.0*pi/2.0;
    }
    if (fabs(y) < eps) {
        if (x > 0)
            return 0.0;
        else return pi;
    }
    double s = fabs(y/(sqrt(x*x+y*y)));
    double ret = asin(s);
    if (x > eps && y > eps) return ret;
    if (x < -eps && y > eps) return pi - ret;
    if (x < -eps && y < -eps) return pi + ret;
    return 2.0*pi - ret;
}

double work(Point point[N], int n) {
    REP1(i, n) point[i].angle = getangle(point[i].x, point[i].y);
    sort(point+1, point+1+n);
    FOR1(i, n+1, n*2) {
        point[i] = point[i-n];
        point[i].angle += 2.0*pi;
    }
    REP1(i, n*2) len[i] = dis(Point(.0,.0), point[i]);
    int be = 1, en = 1;
    buildtree(1, n);
    double ans = 0.0;
    REP1(i, n) {
        double temp = len[i];
        while (point[en].angle - point[i].angle <= pi+eps)
            en++;
        while (point[be].angle - point[i].angle <= pi/3.0+eps)
            be++;
        int be1 = be, en1 = en;
        if (be > n && en > n)
            be -= n, en -= n;
        if (be<en && en <= n+1) {
            temp = min(temp, query(be, en-1));
            ans = max(ans, temp);
        }
        else if (be < en) {
            temp = min(temp, max(query(be, n), query(1, en-1-n)));
            ans = max(ans, temp);
        }
        be = be1, en = en1;
    }
    return ans / 2.0;
}
Point p1[N], p2[N];

int main()
{
    int n; cin >> n;
    REP(i, n) cin >> p1[i].x >> p1[i].y;
    double ans = 0.0;
    REP(i, n) {
        int cnt = 0;
        REP(j, n) {
            if (fabs(p1[i].x-p1[j].x) <= eps && fabs(p1[i].y-p1[j].y) <= eps)
                continue;
            p2[++cnt] = Point(p1[j].x-p1[i].x,p1[j].y-p1[i].y);
        }
        if (cnt >= 2)
            ans = max(ans, work(p2, cnt));
    }
    cout << fixed << setprecision(10) << ans << endl;
    return 0;
}


//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <map>
#include <cassert>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <queue>
#include <complex>
#include <stack>
#include <string>
#include <iomanip>
#include <set>
#include <ctime>
#include <fstream>
#include <list>
#define  inf  0XFFFFFFFFFFFFFFFll
#define  dinf 1e11
#define  N    6111
#define  M    44444
#define  mod  1000000007ll
#define  LL   long long
#define  ULL  unsigned long long
#define  us   unsigned short int
#define  eps  1e-12
#define  pi   acos(-1.0)
#define  REP(i,n)    for (int i=0; i<n; i++)
#define  REP1(i,n)   for (int i=1; i<=n; i++)
#define  FOR(i,l,r)    for (int i=l; i<r; i++)
#define  FOR1(i,l,r) for (int i=l; i<=r; i++)
#define  TXT1

using namespace std;

#ifdef TXT
ifstream fi("in.txt");
#define  cin  fi
#endif

using namespace std;

struct Complex{double x, y;Complex(double _x=0.0,double _y=0.0):x(_x),y(_y){}};
Complex operator + (Complex a,Complex b){return Complex(a.x+b.x,a.y+b.y);}
Complex operator - (Complex a,Complex b){return Complex(a.x-b.x,a.y-b.y);}
Complex operator * (Complex a,Complex b){return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}

struct Point {
    double x, y, angle;
    Point(double xx=0,double yy=0) {x=xx;y=yy;}
    friend bool operator < (Point a, Point b) {return a.angle<b.angle;}
    friend double dis(Point a, Point b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
};

struct Seg {
    int l, r;
    double lm;
} seg[N*4];
double len[N];
void buildtree(int l, int r, int now=1) {
    seg[now].l = l; seg[now].r = r;
    if (l == r) {
        seg[now].lm = len[r];
        return;
    }
    int mid = (l + r) / 2;
    buildtree(l, mid, now*2);
    buildtree(mid+1, r, now*2+1);
    seg[now].lm = max(seg[now*2].lm, seg[now*2+1].lm);
}
double query(int l, int r, int now=1) {
    if (l<=seg[now].l&&seg[now].r<=r)
        return seg[now].lm;
    int mid = (seg[now].l+seg[now].r)/2;
    double ans = 0.0;
    if (l<=mid)
        ans = max(ans, query(l, r, now*2));
    if (r > mid)
        ans = max(ans, query(l, r, now*2+1));
    return ans;
}

double getangle(double x, double y) {
    if (fabs(x) < eps) {
        if (y > 0)
            return pi / 2.0;
        else return 3.0*pi/2.0;
    }
    if (fabs(y) < eps) {
        if (x > 0)
            return 0.0;
        else return pi;
    }
    double s = fabs(y/(sqrt(x*x+y*y)));
    double ret = asin(s);
    if (x > eps && y > eps) return ret;
    if (x < -eps && y > eps) return pi - ret;
    if (x < -eps && y < -eps) return pi + ret;
    return 2.0*pi - ret;
}

double work(Point point[N], int n) {
    REP1(i, n) point[i].angle = getangle(point[i].x, point[i].y);
    sort(point+1, point+1+n);
    FOR1(i, n+1, n*2) {
        point[i] = point[i-n];
        point[i].angle += 2.0*pi;
    }
    REP1(i, n*2) len[i] = dis(Point(.0,.0), point[i]);
    int be = 1, en = 1;
    buildtree(1, n);
    double ans = 0.0;
    REP1(i, n) {
        double temp = len[i];
        while (point[en].angle - point[i].angle <= pi+eps)
            en++;
        while (point[be].angle - point[i].angle <= pi/3.0+eps)
            be++;
        int be1 = be, en1 = en;
        if (be >= en)
            continue;
        if (be > n && en > n)
            be -= n, en -= n;
        if (be<en && en <= n+1) {
            temp = min(temp, query(be, en-1));
            ans = max(ans, temp);
        }
        else if (be < en) {
            temp = min(temp, max(query(be, n), query(1, en-1-n)));
        }
        be = be1, en = en1;
    }
    return ans / 2.0;
}
Point p1[N], p2[N];

int main()
{
    int n; cin >> n;
    REP(i, n) cin >> p1[i].x >> p1[i].y;
    double ans = 0.0;
    REP(i, n) {
        int cnt = 0;
        REP(j, n) {
            if (fabs(p1[i].x-p1[j].x) <= eps && fabs(p1[i].y-p1[j].y) <= eps)
                continue;
            p2[++cnt] = Point(p1[j].x-p1[i].x,p1[j].y-p1[i].y);
        }
        if (cnt >= 2)
            ans = max(ans, work(p2, cnt));
    }
    cout << fixed << setprecision(10) << ans << endl;
    return 0;
}


//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <map>
#include <cassert>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <queue>
#include <complex>
#include <stack>
#include <string>
#include <iomanip>
#include <set>
#include <ctime>
#include <fstream>
#include <list>
#define  inf  0XFFFFFFFFFFFFFFFll
#define  dinf 1e11
#define  N    1111
#define  M    44444
#define  mod  1000000007ll
#define  LL   long long
#define  ULL  unsigned long long
#define  us   unsigned short int
#define  eps  1e-12
#define  pi   acos(-1.0)
#define  REP(i,n)    for (int i=0; i<n; i++)
#define  REP1(i,n)   for (int i=1; i<=n; i++)
#define  FOR(i,l,r)    for (int i=l; i<r; i++)
#define  FOR1(i,l,r) for (int i=l; i<=r; i++)
#define  TXT1

using namespace std;

#ifdef TXT
ifstream fi("in.txt");
#define  cin  fi
#endif

using namespace std;

struct Complex{double x, y;Complex(double _x=0.0,double _y=0.0):x(_x),y(_y){}};
Complex operator + (Complex a,Complex b){return Complex(a.x+b.x,a.y+b.y);}
Complex operator - (Complex a,Complex b){return Complex(a.x-b.x,a.y-b.y);}
Complex operator * (Complex a,Complex b){return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}

struct Point {
    double x, y, angle;
    Point(double xx=0,double yy=0) {x=xx;y=yy;}
    friend bool operator < (Point a, Point b) {return a.angle<b.angle;}
    friend double dis(Point a, Point b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
};

struct Seg {
    int l, r;
    double lm;
} seg[N*4];
double len[N];
void buildtree(int l, int r, int now=1) {
    seg[now].l = l; seg[now].r = r;
    if (l == r) {
        seg[now].lm = len[r];
        return;
    }
    int mid = (l + r) / 2;
    buildtree(l, mid, now*2);
    buildtree(mid+1, r, now*2+1);
    seg[now].lm = max(seg[now*2].lm, seg[now*2+1].lm);
}
double query(int l, int r, int now=1) {
    if (l<=seg[now].l&&seg[now].r<=r)
        return seg[now].lm;
    int mid = (seg[now].l+seg[now].r)/2;
    double ans = 0.0;
    if (l<=mid)
        ans = max(ans, query(l, r, now*2));
    if (r > mid)
        ans = max(ans, query(l, r, now*2+1));
    return ans;
}

double getangle(double x, double y) {
    if (fabs(x) < eps) {
        if (y > 0)
            return pi / 2.0;
        else return 3.0*pi/2.0;
    }
    if (fabs(y) < eps) {
        if (x > 0)
            return 0.0;
        else return pi;
    }
    double s = fabs(y/(sqrt(x*x+y*y)));
    double ret = asin(s);
    if (x > eps && y > eps) return ret;
    if (x < -eps && y > eps) return pi - ret;
    if (x < -eps && y < -eps) return pi + ret;
    return 2.0*pi - ret;
}

double work(Point point[N], int n) {
    REP1(i, n) point[i].angle = getangle(point[i].x, point[i].y);
    sort(point+1, point+1+n);
    FOR1(i, n+1, n*2) {
        point[i] = point[i-n];
        point[i].angle += 2.0*pi;
    }
    REP1(i, n*2) len[i] = dis(Point(.0,.0), point[i]);
    int be = 1, en = 1;
    buildtree(1, n*2);
    double ans = 0.0;
    REP1(i, n) {
        double temp = len[i];
        while (point[en].angle - point[i].angle <= pi+eps)
            en++;
        while (point[be].angle - point[i].angle <= pi/3.0+eps)
            be++;
        if (be<en) {
            temp = min(temp, query(be, en-1));
            ans = max(ans, temp);
        }
    }
    return ans / 2.0;
}
Point p1[N], p2[N];

int main()
{
    int n; cin >> n;
    REP(i, n) cin >> p1[i].x >> p1[i].y;
    double ans = 0.0;
    REP(i, n) {
        int cnt = 0;
        REP(j, n) {
            if (fabs(p1[i].x-p1[j].x) <= eps && fabs(p1[i].y-p1[j].y) <= eps)
                continue;
            p2[++cnt] = Point(p1[j].x-p1[i].x,p1[j].y-p1[i].y);
        }
        if (cnt >= 2)
            ans = max(ans, work(p2, cnt));
    }
    cout << fixed << setprecision(10) << ans << endl;
    return 0;
}


#include <cmath>
#include <cstdio>
#include <algorithm>
#define maxn 3005
#define eps 1e-9
#define pi 3.14159265358979323846
using namespace std;

struct point
{
    int x,y;
    double k;
    point(int _x=0,int _y=0) {x=_x,y=_y,k=atan2(y,x);}
    bool operator <(const point&B) const {return k-B.k<-eps;}
    int dis() {return x*x+y*y;}
} a[maxn],b[maxn];
int N,q[maxn*2][2];

inline bool ok(int i,int j)
{
    double k=abs(b[i].k-b[j].k);
    if (k-pi>eps) k=2*pi-k;
    return k-pi/3>-eps;
}

void push(int p,int l,int&r)
{
    for (;l<=r&&q[r][1]<=b[p].dis(); r--);
    q[++r][0]=p,q[r][1]=b[p].dis();
}

void init()
{
    scanf("%d",&N);
    for (int i=1; i<=N; i++) scanf("%d%d",&a[i].x,&a[i].y);
}

void doit()
{
    int ans=0;
    for (int i=1; i<=N; i++)
    {
        int t=0,l=1,r=0,k;
        for (int j=1; j<=N; j++) b[t+1]=point(a[j].x-a[i].x,a[j].y-a[i].y),t+=b[t+1].x||b[t+1].y;
        sort(b+1,b+t+1);
        for (int j=1; j<=2*N; j++) b[t+j]=b[j];
        for (int j=2; j<=t; j++) if (ok(1,j)) push(j,l,r);
        for (k=t; k&&!ok(1,k); k--);
        if (l<=r) ans=max(ans,min(b[1].dis(),q[l][1]));
        for (int j=2; j<=t; j++)
        {
            for (;l<=r&&!ok(q[l][0],j); l++);
            for (;k-t<=j&&ok(j,k); k++) push(k,l,r);
            if (l<=r) ans=max(ans,min(b[j].dis(),q[l][1]));
        }
    }
    printf("%.20lf\n",sqrt(ans)/2);
}

int main()
{
    init();
    doit();
    return 0;
}


#include <cmath>
#include <cstdio>
#include <algorithm>
#define maxn 3005
#define eps 1e-9
#define pi 3.14159265358979323846
using namespace std;

struct point
{
	int x,y;
	double k;
	point(int _x=0,int _y=0) {x=_x,y=_y,k=atan2(y,x);}
	bool operator <(const point&B) const {return k-B.k<-eps;}
	int dis() {return x*x+y*y;}
} a[maxn],b[maxn*2];
int N,q[maxn][2];

inline bool ok(int i,int j)
{
	double k=abs(b[i].k-b[j].k);
	if (k-pi>eps) k=2*pi-k;
	return k-pi/3>-eps;
}

void push(int p,int l,int&r)
{
	for (;l<=r&&q[r][1]<=b[p].dis(); r--);
	q[++r][0]=p,q[r][1]=b[p].dis();
}

void init()
{
	scanf("%d",&N);
	for (int i=1; i<=N; i++) scanf("%d%d",&a[i].x,&a[i].y);
}

void doit()
{
	int ans=0;
	for (int i=1; i<=N; i++)
	{
		int t=0,l=1,r=0,k;
		for (int j=1; j<=N; j++) b[t+1]=point(a[j].x-a[i].x,a[j].y-a[i].y),t+=b[t+1].x||b[t+1].y;
		sort(b+1,b+t+1);
		for (int j=1; j<=t; j++) b[t+j]=b[j];
		for (int j=2; j<=t; j++) if (ok(1,j)) push(j,l,r);
		for (k=t; k>1&&!ok(1,k); k--);
		if (l<=r) ans=max(ans,min(b[1].dis(),q[l][1]));
		for (int j=2; j<=t; j++)
		{
			for (;l<=r&&!ok(q[l][0],j); l++);
			for (;k-t<j&&ok(j,k); k++) push(k,l,r);
			if (l<=r) ans=max(ans,min(b[j].dis(),q[l][1]));
		}
	}
	printf("%.20lf\n",sqrt(ans)/2);
}

int main()
{
	init();
	doit();
	return 0;
}


#include <cmath>
#include <cstdio>
#include <algorithm>
#define maxn 3005
#define eps 1e-9
#define pi 3.14159265358979323846
using namespace std;

struct point
{
    int x,y;
    double k;
    point(int _x=0,int _y=0) {x=_x,y=_y,k=atan2(y,x);}
    bool operator <(const point&B) const {return k-B.k<-eps;}
    int dis() {return x*x+y*y;}
} a[maxn],b[maxn*2];
int N,q[maxn][2];

inline bool ok(int i,int j)
{
    double k=abs(b[i].k-b[j].k);
    if (k-pi>eps) k=2*pi-k;
    return k-pi/3>-eps;
}

void push(int p,int l,int&r)
{
    for (;l<=r&&q[r][1]<=b[p].dis(); r--);
    q[++r][0]=p,q[r][1]=b[p].dis();
}

void init()
{
    scanf("%d",&N);
    for (int i=1; i<=N; i++) scanf("%d%d",&a[i].x,&a[i].y);
}

void doit()
{
    int ans=0;
    for (int i=1; i<=N; i++)
    {
        int t=0,l=1,r=0,k;
        for (int j=1; j<=N; j++) b[t+1]=point(a[j].x-a[i].x,a[j].y-a[i].y),t+=b[t+1].x||b[t+1].y;
        sort(b+1,b+t+1);
        for (int j=1; j<=2*N; j++) b[t+j]=b[j];
        for (int j=2; j<=t; j++) if (ok(1,j)) push(j,l,r);
        for (k=t; k&&!ok(1,k); k--);
        if (l<=r) ans=max(ans,min(b[1].dis(),q[l][1]));
        for (int j=2; j<=t; j++)
        {
            for (;l<=r&&!ok(q[l][0],j); l++);
            for (;k-t<=j&&ok(j,k); k++) push(k,l,r);
            if (l<=r) ans=max(ans,min(b[j].dis(),q[l][1]));
        }
    }
    printf("%.20lf\n",sqrt(ans)/2);
}

int main()
{
    init();
    doit();
    return 0;
}


#include <cmath>
#include <cstdio>
#include <algorithm>
#define maxn 3005
#define eps 1e-9
#define pi 3.14159265358979323846
using namespace std;

struct point
{
    int x,y;
    double k;
    point(int _x=0,int _y=0) {x=_x,y=_y,k=atan2(y,x);}
    bool operator <(const point&B) const {return k-B.k<-eps;}
    int dis() {return x*x+y*y;}
} a[maxn],b[maxn*2];
int N,q[maxn][2];

inline bool ok(int i,int j)
{
    double k=abs(b[i].k-b[j].k);
    if (k-pi>eps) k=2*pi-k;
    return k-pi/3>-eps;
}

void push(int p,int l,int&r)
{
    for (;l<=r&&q[r][1]<=b[p].dis(); r--);
    q[++r][0]=p,q[r][1]=b[p].dis();
}

void init()
{
    scanf("%d",&N);
    for (int i=1; i<=N; i++) scanf("%d%d",&a[i].x,&a[i].y);
}

void doit()
{
    int ans=0;
    for (int i=1; i<=N; i++)
    {
        int t=0,l=1,r=0,k;
        for (int j=1; j<=N; j++) b[t+1]=point(a[j].x-a[i].x,a[j].y-a[i].y),t+=b[t+1].x||b[t+1].y;
        sort(b+1,b+t+1);
        for (int j=1; j<=2*N; j++) b[t+j]=b[j];
        for (int j=2; j<=t; j++) if (ok(1,j)) push(j,l,r);
        for (k=t; k&&!ok(1,k); k--);
        if (l<=r) ans=max(ans,min(b[1].dis(),q[l][1]));
        for (int j=2; j<=t; j++)
        {
            for (;l<=r&&!ok(q[l][0],j); l++);
            for (;k-t<j&&ok(j,k); k++) push(k,l,r);
            if (l<=r) ans=max(ans,min(b[j].dis(),q[l][1]));
        }
    }
    printf("%.20lf\n",sqrt(ans)/2);
}

int main()
{
    init();
    doit();
    return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

typedef double wtype;

const int MAX = 3002;
const double EPS = 0.000000001;

struct Point {
    double x, y;
    bool operator < (const Point& r) const {
        return x != r.x ? x < r.x : y < r.y;
    }
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

wtype findArea(Point p1, Point p2, Point p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y -
    	   p1.x * p3.y - p2.x * p1.y - p3.x * p2.y ;
}

vector <Point> convexHull(vector <Point> points, int colAllowed = 0) {
	if (points.size() < 3)
		return points;

	vector <Point> lower(points.size()); int lowerSize = 0;
	vector <Point> upper(points.size()); int upperSize = 0;

	sort(points.begin(), points.end());

	for (int i = 0; i < (int)points.size(); i++) {
		// Lower part
		lower[lowerSize++] = points[i];
		while (lowerSize >= 3) {
			wtype area = findArea(lower[lowerSize - 3], lower[lowerSize - 2], lower[lowerSize - 1]);
			if (area > 0 || (colAllowed && fabs(area) < EPS)) break;
			lower[lowerSize - 2] = lower[lowerSize - 1];
			lowerSize--;
		}

		// Upper part
		upper[upperSize++] = points[i];
		while (upperSize >= 3) {
			wtype area = findArea(upper[upperSize - 3], upper[upperSize - 2], upper[upperSize - 1]);
			if (area < 0 || (colAllowed && fabs(area) < EPS)) break;
			upper[upperSize - 2] = upper[upperSize - 1];
			upperSize--;
		}
	}

	vector <Point> ans;

	// Add the upper side
	for (int i = 0; i < upperSize; i++)
		ans.push_back(upper[i]);

	// If two parts end at different points, add the latter
	if (fdist(upper[upperSize - 1], lower[lowerSize - 1]) > EPS)
		ans.push_back(lower[lowerSize - 1]);

	// Add the remaining points from the lower side
	for (int i = lowerSize - 2; i > 0; i--)
		ans.push_back(lower[i]);

	return ans;
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <Point> hull;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                hull.push_back(a[c]);
        }
        hull = convexHull(hull);
        for (int c = 0, j = 0; c < (int)hull.size(); c++) {
            if (j == c) j = (j + 1) % (int)hull.size();
            double dist = fdist(hull[c], hull[j]);
            while (true) {
                int nxt = (j + 1) % (int)hull.size();
                if (nxt == c) break;
                double ndist = fdist(hull[c], hull[nxt]);
                if (ndist > dist) {
                    dist = ndist;
                    j = nxt;
                }
                else break;
            }
            if (dist > r * 2)
                return true;
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 1000000;
	for (int iter = 0; iter < 32; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

const int MAX = 3002;

struct Point {
    double x, y;
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <int> b;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                b.push_back(c);
        }
        for (int c = 0; c < (int)b.size(); c++) {
            for (int j = c + 1; j < (int)b.size(); j++)
                if (dist[b[c]][b[j]] > 2 * r) return true;
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 1000000;
	for (int iter = 0; iter < 64; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

const int MAX = 3002;
const double EPS = 0.000000001;

struct Point {
    int idx;
    double x, y;
    bool operator < (const Point& r) const {
        return x != r.x ? x < r.x : y < r.y;
    }
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

double findArea(Point p1, Point p2, Point p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y -
    	   p1.x * p3.y - p2.x * p1.y - p3.x * p2.y ;
}

int lower[MAX]; int lowerSize;
int upper[MAX]; int upperSize;

void convexHull(vector <int>& points, int colAllowed = 0) {
	if (points.size() < 3)
		return;

    lowerSize = upperSize = 0;
	for (int i = 0; i < (int)points.size(); i++) {
		// Lower part
		lower[lowerSize++] = points[i];
		while (lowerSize >= 3) {
			double area = findArea(a[lower[lowerSize - 3]],
                                   a[lower[lowerSize - 2]],
                                   a[lower[lowerSize - 1]]);
			if (area > 0 || (colAllowed && fabs(area) < EPS)) break;
			lower[lowerSize - 2] = lower[lowerSize - 1];
			lowerSize--;
		}

		// Upper part
		upper[upperSize++] = points[i];
		while (upperSize >= 3) {
			double area = findArea(a[upper[upperSize - 3]],
                                   a[upper[upperSize - 2]],
                                   a[upper[upperSize - 1]]);
			if (area < 0 || (colAllowed && fabs(area) < EPS)) break;
			upper[upperSize - 2] = upper[upperSize - 1];
			upperSize--;
		}
	}

    points.resize(upperSize);
	for (int i = 0; i < upperSize; i++)
		points[i] = upper[i];

	// If two parts end at different points, add the latter
	if (dist[upper[upperSize - 1]][lower[lowerSize - 1]] > EPS)
		points.push_back(lower[lowerSize - 1]);

	// Add the remaining points from the lower side
	for (int i = lowerSize - 2; i > 0; i--)
		points.push_back(lower[i]);
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <int> hull;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                hull.push_back(c);
        }
        convexHull(hull);
        for (int c = 0, j = 0; c < (int)hull.size(); c++) {
            if (j == c) j = (j + 1) % (int)hull.size();
            double cdist = dist[hull[c]][hull[j]];
            if (cdist > r * 2)
                return true;
            while (true) {
                int nxt = (j + 1) % (int)hull.size();
                if (nxt == c) break;
                if (cdist < dist[hull[c]][hull[nxt]]) {
                    cdist = dist[hull[c]][hull[nxt]];
                    if (cdist > r * 2)
                        return true;
                    j = nxt;
                }
                else break;
            }
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);
	sort(a, a + n);
	for (int i = 0; i < n; i++)
	    a[i].idx = i;

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 40000;
	for (int iter = 0; iter < 52; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

const int MAX = 3002;
const double EPS = 0.000000001;

struct Point {
    double x, y;
    bool operator < (const Point& r) const {
        return x != r.x ? x < r.x : y < r.y;
    }
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

double findArea(Point p1, Point p2, Point p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y -
    	   p1.x * p3.y - p2.x * p1.y - p3.x * p2.y ;
}

int lower[MAX]; int lowerSize;
int upper[MAX]; int upperSize;

void convexHull(vector <int>& points, int colAllowed = 0) {
	if (points.size() < 3)
		return;

    lowerSize = upperSize = 0;
	for (int i = 0; i < (int)points.size(); i++) {
		// Lower part
		lower[lowerSize++] = points[i];
		while (lowerSize >= 3) {
			double area = findArea(a[lower[lowerSize - 3]],
                                   a[lower[lowerSize - 2]],
                                   a[lower[lowerSize - 1]]);
			if (area > 0 || (colAllowed && fabs(area) < EPS)) break;
			lower[lowerSize - 2] = lower[lowerSize - 1];
			lowerSize--;
		}

		// Upper part
		upper[upperSize++] = points[i];
		while (upperSize >= 3) {
			double area = findArea(a[upper[upperSize - 3]],
                                   a[upper[upperSize - 2]],
                                   a[upper[upperSize - 1]]);
			if (area < 0 || (colAllowed && fabs(area) < EPS)) break;
			upper[upperSize - 2] = upper[upperSize - 1];
			upperSize--;
		}
	}

    points.resize(upperSize);
	for (int i = 0; i < upperSize; i++)
		points[i] = upper[i];

	// If two parts end at different points, add the latter
	if (dist[upper[upperSize - 1]][lower[lowerSize - 1]] > EPS)
		points.push_back(lower[lowerSize - 1]);

	// Add the remaining points from the lower side
	for (int i = lowerSize - 2; i > 0; i--)
		points.push_back(lower[i]);
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <int> hull;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                hull.push_back(c);
        }
        convexHull(hull);
        for (int c = 0, j = 0; c < (int)hull.size(); c++) {
            if (j == c) j = (j + 1) % (int)hull.size();
            double cdist = dist[hull[c]][hull[j]];
            if (cdist > r * 2)
                return true;
            while (true) {
                int nxt = (j + 1) % (int)hull.size();
                if (nxt == c) break;
                if (cdist < dist[hull[c]][hull[nxt]]) {
                    cdist = dist[hull[c]][hull[nxt]];
                    if (cdist > r * 2)
                        return true;
                    j = nxt;
                }
                else break;
            }
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);
	sort(a, a + n);

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 40000;
	for (int iter = 0; iter < 64; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

typedef double wtype;

const int MAX = 3002;
const double EPS = 0.000000001;

struct Point {
    double x, y;
    bool operator < (const Point& r) const {
        return x != r.x ? x < r.x : y < r.y;
    }
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

wtype findArea(Point p1, Point p2, Point p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y -
    	   p1.x * p3.y - p2.x * p1.y - p3.x * p2.y ;
}

vector <Point> convexHull(vector <Point> points, int colAllowed = 0) {
	if (points.size() < 3)
		return points;

	vector <Point> lower(points.size()); int lowerSize = 0;
	vector <Point> upper(points.size()); int upperSize = 0;

	sort(points.begin(), points.end());

	for (int i = 0; i < (int)points.size(); i++) {
		// Lower part
		lower[lowerSize++] = points[i];
		while (lowerSize >= 3) {
			wtype area = findArea(lower[lowerSize - 3], lower[lowerSize - 2], lower[lowerSize - 1]);
			if (area > 0 || (colAllowed && fabs(area) < EPS)) break;
			lower[lowerSize - 2] = lower[lowerSize - 1];
			lowerSize--;
		}

		// Upper part
		upper[upperSize++] = points[i];
		while (upperSize >= 3) {
			wtype area = findArea(upper[upperSize - 3], upper[upperSize - 2], upper[upperSize - 1]);
			if (area < 0 || (colAllowed && fabs(area) < EPS)) break;
			upper[upperSize - 2] = upper[upperSize - 1];
			upperSize--;
		}
	}

	vector <Point> ans;

	// Add the upper side
	for (int i = 0; i < upperSize; i++)
		ans.push_back(upper[i]);

	// If two parts end at different points, add the latter
	if (fdist(upper[upperSize - 1], lower[lowerSize - 1]) > EPS)
		ans.push_back(lower[lowerSize - 1]);

	// Add the remaining points from the lower side
	for (int i = lowerSize - 2; i > 0; i--)
		ans.push_back(lower[i]);

	return ans;
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <Point> hull;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                hull.push_back(a[c]);
        }
        hull = convexHull(hull);
        for (int c = 0, j = 0; c < (int)hull.size(); c++) {
            if (j == c) j = (j + 1) % (int)hull.size();
            double dist = fdist(hull[c], hull[j]);
            while (true) {
                int nxt = (j + 1) % (int)hull.size();
                if (nxt == c) break;
                double ndist = fdist(hull[c], hull[nxt]);
                if (ndist > dist) {
                    dist = ndist;
                    j = nxt;
                }
                else break;
            }
            if (dist > r * 2)
                return true;
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 40000;
	for (int iter = 0; iter < 32; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

typedef double wtype;

const int MAX = 3002;
const double EPS = 0.000000001;

struct Point {
    int idx;
    double x, y;
    bool operator < (const Point& r) const {
        return x != r.x ? x < r.x : y < r.y;
    }
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

wtype findArea(Point p1, Point p2, Point p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y -
    	   p1.x * p3.y - p2.x * p1.y - p3.x * p2.y ;
}

vector <Point> convexHull(vector <Point> points, int colAllowed = 0) {
	if (points.size() < 3)
		return points;

	vector <Point> lower(points.size()); int lowerSize = 0;
	vector <Point> upper(points.size()); int upperSize = 0;

	for (int i = 0; i < (int)points.size(); i++) {
		// Lower part
		lower[lowerSize++] = points[i];
		while (lowerSize >= 3) {
			wtype area = findArea(lower[lowerSize - 3], lower[lowerSize - 2], lower[lowerSize - 1]);
			if (area > 0 || (colAllowed && fabs(area) < EPS)) break;
			lower[lowerSize - 2] = lower[lowerSize - 1];
			lowerSize--;
		}

		// Upper part
		upper[upperSize++] = points[i];
		while (upperSize >= 3) {
			wtype area = findArea(upper[upperSize - 3], upper[upperSize - 2], upper[upperSize - 1]);
			if (area < 0 || (colAllowed && fabs(area) < EPS)) break;
			upper[upperSize - 2] = upper[upperSize - 1];
			upperSize--;
		}
	}

	vector <Point> ans;

	// Add the upper side
	for (int i = 0; i < upperSize; i++)
		ans.push_back(upper[i]);

	// If two parts end at different points, add the latter
	if (fdist(upper[upperSize - 1], lower[lowerSize - 1]) > EPS)
		ans.push_back(lower[lowerSize - 1]);

	// Add the remaining points from the lower side
	for (int i = lowerSize - 2; i > 0; i--)
		ans.push_back(lower[i]);

	return ans;
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <Point> hull;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                hull.push_back(a[c]);
        }
        hull = convexHull(hull);
        for (int c = 0, j = 0; c < (int)hull.size(); c++) {
            if (j == c) j = (j + 1) % (int)hull.size();
            double cdist = dist[hull[c].idx][hull[j].idx];
            if (cdist > r * 2)
                return true;
            while (true) {
                int nxt = (j + 1) % (int)hull.size();
                if (nxt == c) break;
                double ndist = dist[hull[c].idx][hull[nxt].idx];
                if (ndist > cdist) {
                    cdist = ndist;
                    if (cdist > r * 2)
                        return true;
                    j = nxt;
                }
                else break;
            }
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);
	sort(a, a + n);
	for (int i = 0; i < n; i++)
	    a[i].idx = i;

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 40000;
	for (int iter = 0; iter < 64; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

typedef double wtype;

const int MAX = 3002;
const double EPS = 0.000000001;

struct Point {
    int idx;
    double x, y;
    bool operator < (const Point& r) const {
        return x != r.x ? x < r.x : y < r.y;
    }
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

wtype findArea(Point p1, Point p2, Point p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y -
    	   p1.x * p3.y - p2.x * p1.y - p3.x * p2.y ;
}

Point lower[MAX]; int lowerSize;
Point upper[MAX]; int upperSize;

void convexHull(vector <Point>& points, int colAllowed = 0) {
	if (points.size() < 3)
		return;

    lowerSize = upperSize = 0;
	for (int i = 0; i < (int)points.size(); i++) {
		// Lower part
		lower[lowerSize++] = points[i];
		while (lowerSize >= 3) {
			wtype area = findArea(lower[lowerSize - 3], lower[lowerSize - 2], lower[lowerSize - 1]);
			if (area > 0 || (colAllowed && fabs(area) < EPS)) break;
			lower[lowerSize - 2] = lower[lowerSize - 1];
			lowerSize--;
		}

		// Upper part
		upper[upperSize++] = points[i];
		while (upperSize >= 3) {
			wtype area = findArea(upper[upperSize - 3], upper[upperSize - 2], upper[upperSize - 1]);
			if (area < 0 || (colAllowed && fabs(area) < EPS)) break;
			upper[upperSize - 2] = upper[upperSize - 1];
			upperSize--;
		}
	}

    points.resize(upperSize);
	for (int i = 0; i < upperSize; i++)
		points[i] = upper[i];

	// If two parts end at different points, add the latter
	if (fdist(upper[upperSize - 1], lower[lowerSize - 1]) > EPS)
		points.push_back(lower[lowerSize - 1]);

	// Add the remaining points from the lower side
	for (int i = lowerSize - 2; i > 0; i--)
		points.push_back(lower[i]);
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <Point> hull;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                hull.push_back(a[c]);
        }
        convexHull(hull);
        for (int c = 0, j = 0; c < (int)hull.size(); c++) {
            if (j == c) j = (j + 1) % (int)hull.size();
            double cdist = dist[hull[c].idx][hull[j].idx];
            if (cdist > r * 2)
                return true;
            while (true) {
                int nxt = (j + 1) % (int)hull.size();
                if (nxt == c) break;
                double ndist = dist[hull[c].idx][hull[nxt].idx];
                if (ndist > cdist) {
                    cdist = ndist;
                    if (cdist > r * 2)
                        return true;
                    j = nxt;
                }
                else break;
            }
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);
	sort(a, a + n);
	for (int i = 0; i < n; i++)
	    a[i].idx = i;

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 40000;
	for (int iter = 0; iter < 64; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

typedef double wtype;

const int MAX = 3002;
const double EPS = 0.000000001;

struct Point {
    double x, y;
    bool operator < (const Point& r) const {
        return x != r.x ? x < r.x : y < r.y;
    }
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

wtype findArea(Point p1, Point p2, Point p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y -
    	   p1.x * p3.y - p2.x * p1.y - p3.x * p2.y ;
}

vector <Point> convexHull(vector <Point> points, int colAllowed = 0) {
	if (points.size() < 3)
		return points;

	vector <Point> lower(points.size()); int lowerSize = 0;
	vector <Point> upper(points.size()); int upperSize = 0;

	sort(points.begin(), points.end());

	for (int i = 0; i < (int)points.size(); i++) {
		// Lower part
		lower[lowerSize++] = points[i];
		while (lowerSize >= 3) {
			wtype area = findArea(lower[lowerSize - 3], lower[lowerSize - 2], lower[lowerSize - 1]);
			if (area > 0 || (colAllowed && fabs(area) < EPS)) break;
			lower[lowerSize - 2] = lower[lowerSize - 1];
			lowerSize--;
		}

		// Upper part
		upper[upperSize++] = points[i];
		while (upperSize >= 3) {
			wtype area = findArea(upper[upperSize - 3], upper[upperSize - 2], upper[upperSize - 1]);
			if (area < 0 || (colAllowed && fabs(area) < EPS)) break;
			upper[upperSize - 2] = upper[upperSize - 1];
			upperSize--;
		}
	}

	vector <Point> ans;

	// Add the upper side
	for (int i = 0; i < upperSize; i++)
		ans.push_back(upper[i]);

	// If two parts end at different points, add the latter
	if (fdist(upper[upperSize - 1], lower[lowerSize - 1]) > EPS)
		ans.push_back(lower[lowerSize - 1]);

	// Add the remaining points from the lower side
	for (int i = lowerSize - 2; i > 0; i--)
		ans.push_back(lower[i]);

	return ans;
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <Point> hull;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                hull.push_back(a[c]);
        }
        hull = convexHull(hull);
        for (int c = 0, j = 0; c < (int)hull.size(); c++) {
            if (j == c) j = (j + 1) % (int)hull.size();
            double dist = fdist(hull[c], hull[j]);
            while (true) {
                int nxt = (j + 1) % (int)hull.size();
                if (nxt == c) break;
                double ndist = fdist(hull[c], hull[nxt]);
                if (ndist > dist) {
                    dist = ndist;
                    j = nxt;
                }
                else break;
            }
            if (dist > r * 2)
                return true;
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 40000;
	for (int iter = 0; iter < 48; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
FILE *in; FILE *out;

typedef double wtype;

const int MAX = 3002;
const double EPS = 0.000000001;

struct Point {
    double x, y;
    bool operator < (const Point& r) const {
        return x != r.x ? x < r.x : y < r.y;
    }
};

int n;
Point a[MAX];
double dist[MAX][MAX];

double fdist(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

wtype findArea(Point p1, Point p2, Point p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y -
    	   p1.x * p3.y - p2.x * p1.y - p3.x * p2.y ;
}

vector <Point> convexHull(vector <Point> points, int colAllowed = 0) {
	if (points.size() < 3)
		return points;

	vector <Point> lower(points.size()); int lowerSize = 0;
	vector <Point> upper(points.size()); int upperSize = 0;

	sort(points.begin(), points.end());

	for (int i = 0; i < (int)points.size(); i++) {
		// Lower part
		lower[lowerSize++] = points[i];
		while (lowerSize >= 3) {
			wtype area = findArea(lower[lowerSize - 3], lower[lowerSize - 2], lower[lowerSize - 1]);
			if (area > 0 || (colAllowed && fabs(area) < EPS)) break;
			lower[lowerSize - 2] = lower[lowerSize - 1];
			lowerSize--;
		}

		// Upper part
		upper[upperSize++] = points[i];
		while (upperSize >= 3) {
			wtype area = findArea(upper[upperSize - 3], upper[upperSize - 2], upper[upperSize - 1]);
			if (area < 0 || (colAllowed && fabs(area) < EPS)) break;
			upper[upperSize - 2] = upper[upperSize - 1];
			upperSize--;
		}
	}

	vector <Point> ans;

	// Add the upper side
	for (int i = 0; i < upperSize; i++)
		ans.push_back(upper[i]);

	// If two parts end at different points, add the latter
	if (fdist(upper[upperSize - 1], lower[lowerSize - 1]) > EPS)
		ans.push_back(lower[lowerSize - 1]);

	// Add the remaining points from the lower side
	for (int i = lowerSize - 2; i > 0; i--)
		ans.push_back(lower[i]);

	return ans;
}

bool eval(double r) {
    for (int i = 0; i < n; i++) {
        vector <Point> hull;
        for (int c = i + 1; c < n; c++) {
            if (dist[i][c] > 2 * r)
                hull.push_back(a[c]);
        }
        hull = convexHull(hull);
        for (int c = 0, j = 0; c < (int)hull.size(); c++) {
            if (j == c) j = (j + 1) % (int)hull.size();
            double dist = fdist(hull[c], hull[j]);
            while (true) {
                int nxt = (j + 1) % (int)hull.size();
                if (nxt == c) break;
                double ndist = fdist(hull[c], hull[nxt]);
                if (ndist > dist) {
                    dist = ndist;
                    j = nxt;
                }
                else break;
            }
            if (dist > r * 2)
                return true;
        }
    }
    return false;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("E.in", "rt"); out = fopen("E.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++)
	    fscanf(in, "%lf %lf", &a[i].x, &a[i].y);

	for (int i = 0; i < n; i++)
	    for (int c = 0; c < n; c++)
	        dist[i][c] = fdist(a[i], a[c]);

	double ans = 0.0;
	double left = 0.0, right = 1000000;
	for (int iter = 0; iter < 64; iter++) {
	    double mid = (left + right) / 2.0;
	    if (eval(mid))
	        left = mid, ans = mid;
	    else
	        right = mid;
	}
	fprintf(out, "%.9lf\n", ans);
	return 0;
}


#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
using namespace std;

#define FOR0(i,n) for( i = 0 ; i < n ; ++i )
#define FOR1(i,n) for( i = 1 ; i <= n ; ++i )
#define sys_p system( "pause" )
#define pb push_back
#define mp make_pair

typedef long long LL ;
typedef vector < LL > vl ;
typedef vector < vl > vvl ;
typedef vector < vvl > vvvl ;

const LL INF = (LL)1e18 ;

ifstream Cin( "input.txt" ) ;
ofstream Cout( "output.txt" ) ;

struct pt
{
      double x, y ;
};

struct line
{
      double a, b, c ;
      void init( pt p, pt q )
      {
           a = p.y-q.y ;
           b = q.x-p.x ;
           c = -a*p.x-b*p.y ;
      }
};

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

bool cmp( 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 sqdist( pt a, pt b )
{
      return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ;
}

pt intersect( pt p, line q )
{
      /*cout << "intersect" << endl ;
      cout << p.x << " " << p.y << endl ;
      cout << q.a << " " << q.b << " " << q.c << endl ;
      sys_p ;
      */
      pt dd ;
      if( q.a == 0 ){ dd.x = p.x ; dd.y = -q.c * 1./q.b ; return dd ; }
      else if( q.b == 0 ){ dd.x = -q.c * 1./q.a ; dd.y = p.y ; return dd ; }
      double k2 = q.b / q.a , b2 = p.y - p.x * k2 ;
      line q2 ; q2.a = k2 ; q2.b = -1 ; q2.c = b2 ;
      dd.x = -(q.c*q2.b-q2.c*q.b)*1./(q.a*q2.b-q2.a*q.b) ;
      dd.y = -(q.a*q2.c-q2.a*q.c)*1./(q.a*q2.b-q2.a*q.b) ;

      //cout << (q.a*q2.b-q2.a*q.b) << " " ; sys_p ;

      return dd ;
}

main()
{
      int n, i, j, k ; double Min, Max, M ;
      cin >> n ; vector < pt > r(n) ; FOR0( i, n ) cin >> r[i].x >> r[i].y ;
      sort( r.begin(), r.end() ) ;
      Min = 0. ; Max = 1e6 ;
      while( Min + 1e-6 < Max )
      {
             bool g = false ;
             M = (Min+Max)/2. ;

             //cout << M << " " << Min << " " << Max << endl ;

             FOR0( i, n )
             {
                   vector < pt > m, up, down ;
                   FOR0( j, n ) if( j != i )
                     if( sqdist( r[i], r[j] ) * 1. >= 4.*M*M )
                       m.pb( r[j] ) ;
                   if( (int)m.size() < 2 ) continue ;
                   if( (int)m.size() == 2 )
                   {
                        if( sqdist( m[0], m[1] ) * 1. >= 4*M*M )
                        {
                            g = true ;
                            break ;
                        }
                        continue ;
                   }
                   //cout << "Before G" << endl ;
                   /*Grekhem*/
                   pt ptf = m[0], ptl = m.back() ;
                   up.pb( ptf ) ; down.pb( ptf ) ;
                   for( j = 1 ; j < (int)m.size() ; j++ )
                   {
                        if( j == (int)m.size()-1 || cmp( ptf, m[j], ptl ) )
                        {
                            while( (int)up.size() >= 2 && !cmp( up[ (int)up.size()-2 ], up.back(), m[j] ) )
                              up.pop_back() ;
                            up.pb( m[j] ) ;
                        }
                        if( j == (int)m.size()-1 || !cmp( ptf, m[j], ptl ) )
                        {
                            while( (int)down.size() >= 2 && cmp( down[ (int)down.size()-2 ], down.back(), m[j] ) )
                              down.pop_back() ;
                            down.pb( m[j] ) ;
                        }
                   /*cout << "up" << endl ;
                   FOR0( k, (int)up.size() )
                     cout << up[k].x << " " << up[k].y << endl ;
                   cout << "down" << endl ;
                   FOR0( k, (int)down.size() )
                     cout << down[k].x << " " << down[k].y << endl ;
                   cout << endl ;*/
                   }
                   m.clear() ;
                   FOR0( j, (int)up.size() ) m.pb( up[j] ) ;
                   for( j = (int)down.size()-2 ; j > 0 ; --j ) m.pb( down[j] ) ;
                   //cout << "Before Bd" << endl ;
                   /*Biggest distance*/
                   j = 0 ; k = 2 ;
                   while( j < (int)m.size() )
                   {
                          //cout << j << endl ;
                          line cur ; pt curi, nexti ;
                          cur.init( m[j], m[(j+1)%(int)m.size()] ) ;
                          while( true )
                          {
                            int nextk = (k+1)%(int)m.size() ;
                            /*cout << j << " " << k << endl ;
                            curi = intersect( m[k], cur ) ;
                            cout << m[k].x << " " << m[k].y << endl ;
                            cout << m[j].x << " " << m[j].y << endl ;
                            cout << m[(j+1)%(int)m.size()].x << " " << m[(j+1)%(int)m.size()].y << endl ;
                            cout << curi.x << " " << curi.y << endl ; sys_p ;*/
                            nexti = intersect( m[nextk], cur ) ;
                            if( sqdist( m[k], curi ) > sqdist( m[nextk], nexti ) )
                              break ;
                            k = nextk ;
                          }
                          curi = intersect( m[k], cur ) ;
                          if( sqdist( m[k], curi ) >= 4.*M*M )
                          {
                              g = true ;
                              break ;
                          }
                          j++ ;
                   }
                   if( g ) break ;
             }
             //if( (int)m.size() >= 2 )
             //cout << m[0].x << " " << m[0].y << "   " << m[1].x << " " << m[1].y << "   " << sqdist( m[0], m[1] ) << " " << 4.*M*M << endl ;
             if( g ) Min = M ; else Max = M-1e-6 ;
      }
      printf( "%.6f", Min ) ;
}


#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
using namespace std;

#define FOR0(i,n) for( i = 0 ; i < n ; ++i )
#define FOR1(i,n) for( i = 1 ; i <= n ; ++i )
#define sys_p system( "pause" )
#define pb push_back
#define mp make_pair

typedef long long LL ;
typedef vector < LL > vl ;
typedef vector < vl > vvl ;
typedef vector < vvl > vvvl ;

const LL INF = (LL)1e18 ;

ifstream Cin( "input.txt" ) ;
ofstream Cout( "output.txt" ) ;

struct pt
{
      double x, y ;
};

struct line
{
      double a, b, c ;
      void init( pt p, pt q )
      {
           a = p.y-q.y ;
           b = q.x-p.x ;
           c = -a*p.x-b*p.y ;
      }
};

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

bool cmp( 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 sqdist( pt a, pt b )
{
      return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ;
}

pt intersect( pt p, line q )
{
      /*cout << "intersect" << endl ;
      cout << p.x << " " << p.y << endl ;
      cout << q.a << " " << q.b << " " << q.c << endl ;
      sys_p ;
      */
      pt dd ;
      if( q.a == 0 ){ dd.x = p.x ; dd.y = -q.c * 1./q.b ; return dd ; }
      else if( q.b == 0 ){ dd.x = -q.c * 1./q.a ; dd.y = p.y ; return dd ; }
      double k2 = q.b / q.a , b2 = p.y - p.x * k2 ;
      line q2 ; q2.a = k2 ; q2.b = -1 ; q2.c = b2 ;
      dd.x = -(q.c*q2.b-q2.c*q.b)*1./(q.a*q2.b-q2.a*q.b) ;
      dd.y = -(q.a*q2.c-q2.a*q.c)*1./(q.a*q2.b-q2.a*q.b) ;

      //cout << (q.a*q2.b-q2.a*q.b) << " " ; sys_p ;

      return dd ;
}

main()
{
      int n, i, j, k ; double Min, Max, M ;
      cin >> n ; vector < pt > r(n) ; FOR0( i, n ) cin >> r[i].x >> r[i].y ;
      sort( r.begin(), r.end() ) ;
      Min = 0. ; Max = 1e5 ;
      while( Min + 1e-7 < Max )
      {
             bool g = false ;
             M = (Min+Max)/2. ;

             //cout << M << " " << Min << " " << Max << endl ;

             FOR0( i, n )
             {
                   vector < pt > m, up, down ;
                   FOR0( j, n ) if( j != i )
                     if( sqdist( r[i], r[j] ) * 1. >= 4.*M*M )
                       m.pb( r[j] ) ;
                   if( (int)m.size() < 2 ) continue ;
                   if( (int)m.size() == 2 )
                   {
                        if( sqdist( m[0], m[1] ) * 1. >= 4*M*M )
                        {
                            g = true ;
                            break ;
                        }
                        continue ;
                   }
                   //cout << "Before G" << endl ;
                   /*Grekhem*/
                   pt ptf = m[0], ptl = m.back() ;
                   up.pb( ptf ) ; down.pb( ptf ) ;
                   for( j = 1 ; j < (int)m.size() ; j++ )
                   {
                        if( j == (int)m.size()-1 || cmp( ptf, m[j], ptl ) )
                        {
                            while( (int)up.size() >= 2 && !cmp( up[ (int)up.size()-2 ], up.back(), m[j] ) )
                              up.pop_back() ;
                            up.pb( m[j] ) ;
                        }
                        if( j == (int)m.size()-1 || !cmp( ptf, m[j], ptl ) )
                        {
                            while( (int)down.size() >= 2 && cmp( down[ (int)down.size()-2 ], down.back(), m[j] ) )
                              down.pop_back() ;
                            down.pb( m[j] ) ;
                        }
                   /*cout << "up" << endl ;
                   FOR0( k, (int)up.size() )
                     cout << up[k].x << " " << up[k].y << endl ;
                   cout << "down" << endl ;
                   FOR0( k, (int)down.size() )
                     cout << down[k].x << " " << down[k].y << endl ;
                   cout << endl ;*/
                   }
                   m.clear() ;
                   FOR0( j, (int)up.size() ) m.pb( up[j] ) ;
                   for( j = (int)down.size()-2 ; j > 0 ; --j ) m.pb( down[j] ) ;
                   //cout << "Before Bd" << endl ;
                   /*Biggest distance*/
                   j = 0 ; k = 2 ;
                   while( j < (int)m.size() )
                   {
                          //cout << j << endl ;
                          line cur ; pt curi, nexti ;
                          cur.init( m[j], m[(j+1)%(int)m.size()] ) ;
                          while( true )
                          {
                            int nextk = (k+1)%(int)m.size() ;
                            /*cout << j << " " << k << endl ;
                            curi = intersect( m[k], cur ) ;
                            cout << m[k].x << " " << m[k].y << endl ;
                            cout << m[j].x << " " << m[j].y << endl ;
                            cout << m[(j+1)%(int)m.size()].x << " " << m[(j+1)%(int)m.size()].y << endl ;
                            cout << curi.x << " " << curi.y << endl ; sys_p ;*/
                            nexti = intersect( m[nextk], cur ) ;
                            if( sqdist( m[k], curi ) > sqdist( m[nextk], nexti ) )
                              break ;
                            k = nextk ;
                          }
                          curi = intersect( m[k], cur ) ;
                          if( sqdist( m[k], curi ) >= 4.*M*M )
                          {
                              g = true ;
                              break ;
                          }
                          j++ ;
                   }
                   if( g ) break ;
             }
             //if( (int)m.size() >= 2 )
             //cout << m[0].x << " " << m[0].y << "   " << m[1].x << " " << m[1].y << "   " << sqdist( m[0], m[1] ) << " " << 4.*M*M << endl ;
             if( g ) Min = M ; else Max = M-1e-7 ;
      }
      printf( "%.6f", Min ) ;
}


#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
using namespace std;

#define FOR0(i,n) for( i = 0 ; i < n ; ++i )
#define FOR1(i,n) for( i = 1 ; i <= n ; ++i )
#define sys_p system( "pause" )
#define pb push_back
#define mp make_pair

typedef long long LL ;
typedef vector < LL > vl ;
typedef vector < vl > vvl ;
typedef vector < vvl > vvvl ;

const LL INF = (LL)1e18 ;

ifstream Cin( "input.txt" ) ;
ofstream Cout( "output.txt" ) ;

struct pt
{
      double x, y ;
};

struct line
{
      double a, b, c ;
      void init( pt p, pt q )
      {
           a = p.y-q.y ;
           b = q.x-p.x ;
           c = -a*p.x-b*p.y ;
      }
};

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

bool cmpm( 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 cmpb( 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 sqdist( pt a, pt b )
{
      return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ;
}

pt intersect( pt p, line q )
{
      /*cout << "intersect" << endl ;
      cout << p.x << " " << p.y << endl ;
      cout << q.a << " " << q.b << " " << q.c << endl ;
      sys_p ;
      */
      pt dd ;
      if( q.a == 0 ){ dd.x = p.x ; dd.y = -q.c * 1./q.b ; return dd ; }
      else if( q.b == 0 ){ dd.x = -q.c * 1./q.a ; dd.y = p.y ; return dd ; }
      double k2 = q.b / q.a , b2 = p.y - p.x * k2 ;
      line q2 ; q2.a = k2 ; q2.b = -1 ; q2.c = b2 ;
      dd.x = -(q.c*q2.b-q2.c*q.b)*1./(q.a*q2.b-q2.a*q.b) ;
      dd.y = -(q.a*q2.c-q2.a*q.c)*1./(q.a*q2.b-q2.a*q.b) ;

      //cout << (q.a*q2.b-q2.a*q.b) << " " ; sys_p ;

      return dd ;
}

main()
{
      int n, i, j, k ; double Min, Max, M ;
      cin >> n ; vector < pt > r(n) ; FOR0( i, n ) cin >> r[i].x >> r[i].y ;
      sort( r.begin(), r.end() ) ;
      Min = 0. ; Max = 1e6 ;
      while( Min + 1e-6 < Max )
      {
             bool g = false ;
             M = (Min+Max)/2. ;

             //cout << M << " " << Min << " " << Max << endl ;

             FOR0( i, n )
             {
                   vector < pt > m, up, down ;
                   FOR0( j, n ) if( j != i )
                     if( sqdist( r[i], r[j] ) * 1. >= 4.*M*M )
                       m.pb( r[j] ) ;
                   if( (int)m.size() < 2 ) continue ;
                   if( (int)m.size() == 2 )
                   {
                        if( sqdist( m[0], m[1] ) * 1. >= 4*M*M )
                        {
                            g = true ;
                            break ;
                        }
                        continue ;
                   }
                   //cout << "Before G" << endl ;
                   /*Grekhem*/
                   pt ptf = m[0], ptl = m.back() ;
                   up.pb( ptf ) ; down.pb( ptf ) ;
                   for( j = 1 ; j < (int)m.size() ; j++ )
                   {
                        if( j == (int)m.size()-1 || cmpm( ptf, m[j], ptl ) )
                        {
                            while( (int)up.size() >= 2 && !cmpm( up[ (int)up.size()-2 ], up.back(), m[j] ) )
                              up.pop_back() ;
                            up.pb( m[j] ) ;
                        }
                        if( j == (int)m.size()-1 || cmpb( ptf, m[j], ptl ) )
                        {
                            while( (int)down.size() >= 2 && !cmpb( down[ (int)down.size()-2 ], down.back(), m[j] ) )
                              down.pop_back() ;
                            down.pb( m[j] ) ;
                        }
                   /*cout << "up" << endl ;
                   FOR0( k, (int)up.size() )
                     cout << up[k].x << " " << up[k].y << endl ;
                   cout << "down" << endl ;
                   FOR0( k, (int)down.size() )
                     cout << down[k].x << " " << down[k].y << endl ;
                   cout << endl ;*/
                   }
                   m.clear() ;
                   FOR0( j, (int)up.size() ) m.pb( up[j] ) ;
                   for( j = (int)down.size()-2 ; j > 0 ; --j ) m.pb( down[j] ) ;
                   //cout << "Before Bd" << endl ;
                   /*Biggest distance*/
                   j = 0 ; k = 2 ;
                   while( j < (int)m.size() )
                   {
                          //cout << j << endl ;
                          line cur ; pt curi, nexti ;
                          cur.init( m[j], m[(j+1)%(int)m.size()] ) ;
                          while( true )
                          {
                            int nextk = (k+1)%(int)m.size() ;
                            /*cout << j << " " << k << endl ;
                            curi = intersect( m[k], cur ) ;
                            cout << m[k].x << " " << m[k].y << endl ;
                            cout << m[j].x << " " << m[j].y << endl ;
                            cout << m[(j+1)%(int)m.size()].x << " " << m[(j+1)%(int)m.size()].y << endl ;
                            cout << curi.x << " " << curi.y << endl ; sys_p ;*/
                            nexti = intersect( m[nextk], cur ) ;
                            if( sqdist( m[k], curi ) > sqdist( m[nextk], nexti ) )
                              break ;
                            k = nextk ;
                          }
                          curi = intersect( m[k], cur ) ;
                          if( sqdist( m[k], curi ) >= 4.*M*M )
                          {
                              g = true ;
                              break ;
                          }
                          j++ ;
                   }
                   if( g ) break ;
             }
             //if( (int)m.size() >= 2 )
             //cout << m[0].x << " " << m[0].y << "   " << m[1].x << " " << m[1].y << "   " << sqdist( m[0], m[1] ) << " " << 4.*M*M << endl ;
             if( g ) Min = M ; else Max = M-1e-6 ;
      }
      printf( "%.6f", Min ) ;
}


#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
using namespace std;

#define FOR0(i,n) for( i = 0 ; i < n ; ++i )
#define FOR1(i,n) for( i = 1 ; i <= n ; ++i )
#define sys_p system( "pause" )
#define pb push_back
#define mp make_pair

typedef long long LL ;
typedef vector < LL > vl ;
typedef vector < vl > vvl ;
typedef vector < vvl > vvvl ;

const LL INF = (LL)1e18 ;

ifstream Cin( "input.txt" ) ;
ofstream Cout( "output.txt" ) ;

main()
{
      int n, i, j, x[3000], y[3000] ; bitset <3000> k[3000] ;cin >> n ;
      vector < pair < int, pair < int, int > > > g ;
      FOR0( i, n ) cin >> x[i] >> y[i] ;
      FOR0( i, n ) for( j = i+1 ; j < n ; j++ ) g.pb( mp( (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]), mp( i,j ) ) ) ;
      sort( g.rbegin(), g.rend() ) ;
      FOR0( i, (int)g.size() )
      {
            int a = g[i].second.first, b = g[i].second.second ;
            if( ( k[a] & k[b] ).any() ) { printf( "%.6f", sqrt( g[i].first ) / 2. ) ; return 0 ; }
            k[a][b] = k[b][a] = 1 ;
      }
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=4000;
const double eps=1e-8,inf=1e50,Pi=acos(-1.0);
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
} o,po[MAXN];
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b) {
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
struct data{
    double x,y,angle,dist2;
    data(){}
    data(double _x,double _y,double _a,double _d){
        x=_x;
        y=_y;
        angle=_a;
        dist2=_d;
    }
}temp[MAXN];
bool comp_angle(const data a,const data b) {
   int tmp=sign(a.angle-b.angle);
   if(tmp<0||(tmp==0&&a.dist2<b.dist2))return true;
   else return false;
}
double st[20][MAXN];
int ln[MAXN];
void init(){
    for(int i=2,j=0,temp=0;j<MAXN;i<<=1,temp++){
        for(;j<i&&j<MAXN;j++){
            ln[j]=temp;
        }
    }
}
void init_rmq(int n){
    int i,j,k,sk;
    for(i=0;i<n;i++)st[0][i]=temp[i].dist2;
    for(i=1,k=2;k<n;i++,k<<=1){
        for(j=0,sk=(k>>1);j+k-1<=n;++j,++sk){
            st[i][j]=st[i-1][j];
            if(sk<n&&st[i][j]<st[i-1][sk])
                st[i][j]=st[i-1][sk];
        }
    }
}
double query(int x,int y){
    if(x>y)return 0.0;
    int b=ln[y-x+1];
    return max(st[b][x],st[b][y-(1<<b)+1]);
}
double ans;
void solve(int n,int center){
    int num=0;
    bool flag=false;
    for(int i=0;i<n;i++){
        if(i==center)continue;
        temp[num]=data(po[i].x,po[i].y,atan2(po[i].y-po[center].y,po[i].x-po[center].x),getdist2(po[i],po[center]));
        if(temp[num].dist2>ans)
            flag=true;
        num++;
    }
    if(!flag)return;
    sort(temp,temp+num,comp_angle);
    temp[num].angle=inf;
    init_rmq(num);
    for(int i=0;i<num;i++){
        int ll=i+1,rr=num,mid,lp,rp;
        while(ll<rr){
            mid=(ll+rr)>>1;
            if(temp[mid].angle-temp[i].angle>Pi/3.0-eps)
                rr=mid;
            else
                ll=mid+1;
        }
        if(rr==num)
            break;
        lp=rr;
        ll=i+1,rr=num;
        while(ll<rr){
            mid=(ll+rr)>>1;
            if(temp[mid].angle-temp[i].angle>5.0*Pi/3.0+eps)
                rr=mid;
            else
                ll=mid+1;
        }
        rp=rr-1;
        ans=max(ans,min(temp[i].dist2,query(lp,rp)));
    }
}
int main() {
    //freopen("data.in","r",stdin);
    int n;
    init();
    while(scanf("%d",&n)!=EOF) {
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&po[i].x,&po[i].y);
        ans=0;
        for(int i=0;i<n;i++)
            solve(n,i);
        printf("%lf\n",sqrt(ans)/2.0);
    }
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=4000;
const double eps=1e-8,inf=1e50;
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
};
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b){
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
inline double getdist(point a,point b){
    return sqrt(getdist2(a,b));
}
bool comp_cod(const point a,const point b){
    return a.x<b.x||((sign(a.x-b.x)==0)&&a.y<b.y);
}
vector<point> adjust_convex_hull(vector<point> p,int first){
    int i,j,k,id;
    vector<point> pg;
    for(i=0;i<first;i++){
        pg.push_back(p[i]);
    }
    double mf;
    for(j=first;j<p.size();){
        i=j;
        pg.push_back(p[j++]);
        if(j==p.size())
            break;
        pg.push_back(p[j++]);
        while(j<p.size()&&sign(xmult(p[i],p[i+1],p[j]))==0){
            j++;
        }
        j--;
        if(sign(xmult(p[i],p[i+1],p[j]))==0&&j-i+1>3)
        {
            mf=0;id=-1;
            for(k=i+1;k<j;k++){
                double tmp=min(getdist2(p[i],p[k]),getdist2(p[k],p[j]));
                if(tmp>mf){
                    mf=tmp;
                    id=k;
                }
            }
            pg.pop_back();
            pg.push_back(p[id]);
            pg.push_back(p[j++]);
        }
        else if(j!=i+1){
            pg.push_back(p[j++]);
        }
        else
            j++;
    }
    return pg;
}
vector<point> convex_hull(vector<point> p){
    int i,j,top;
    sort(p.begin(),p.end(),comp_cod);
    vector<point> pg;
    for(i=top=0;i<p.size();i++)
    {
        while(top>1&&xmult(pg[top-2],pg[top-1],p[i])<-eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    pg=adjust_convex_hull(pg,0);
    j=top=pg.size();
    for(i=p.size()-2;i>=0;i--)
    {
        while(top>j&&xmult(pg[top-2],pg[top-1],p[i])<-eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    pg=adjust_convex_hull(pg,j-1);
    pg.pop_back();
    return pg;
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        vector<point> p;
        point tmp;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&tmp.x,&tmp.y);
            p.push_back(tmp);
        }
        p=convex_hull(p);
        n=p.size();
        double ans=0;
        for(int i=0;i<n-2;i++){
            for(int j=i+1;j<n-1;j++){
                double dm,dij=getdist2(p[i],p[j]),dik,djk;
                if(ans>dij)
                    continue;
                for(int k=j+1;k<n;k++){
                    djk=getdist2(p[j],p[k]);
                    dik=getdist2(p[i],p[k]);
                    dm=min(min(dij,djk),dik);
                    if(dm>ans)ans=dm;
                    if(sign(dm-dij)==0)
                        break;
                }

            }
        }
        printf("%lf\n",sqrt(ans)/2.0);
    }
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=4000;
const double eps=1e-8,inf=1e50,Pi=acos(-1.0),Pi3=Pi/3.0;
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
} o,po[MAXN];
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b) {
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
struct data{
    double angle,dist2;
    data(){}
    data(double _a,double _d){
        angle=_a;
        dist2=_d;
    }
}temp[MAXN];
bool comp_angle(const data a,const data b) {
   int tmp=sign(a.angle-b.angle);
   if(tmp<0||(tmp==0&&a.dist2<b.dist2))return true;
   else return false;
}
double st[20][MAXN];
int ln[MAXN];
void init(){
    for(int i=2,j=0,temp=0;j<MAXN;i<<=1,temp++){
        for(;j<i&&j<MAXN;j++){
            ln[j]=temp;
        }
    }
}
void init_rmq(int n){
    int i,j,k,sk;
    for(i=0;i<n;i++)st[0][i]=temp[i].dist2;
    for(i=1,k=2;k<n;i++,k<<=1){
        for(j=0,sk=(k>>1);j+k-1<=n;++j,++sk){
            st[i][j]=st[i-1][j];
            if(sk<n&&st[i][j]<st[i-1][sk])
                st[i][j]=st[i-1][sk];
        }
    }
}
double query(int x,int y){
    if(x>y)return 0.0;
    int b=ln[y-x+1];
    return max(st[b][x],st[b][y-(1<<b)+1]);
}
double ans;
void solve(int n,int center){
    int num=0;
    bool flag=false;
    for(int i=0;i<n;i++){
        if(i==center)continue;
        temp[num]=data(atan2(po[i].y-po[center].y,po[i].x-po[center].x),getdist2(po[i],po[center]));
        if(temp[num].dist2>ans)
            flag=true;
        num++;
    }
    if(!flag)return;
    sort(temp,temp+num,comp_angle);
    temp[num].angle=inf;
    init_rmq(num);
    for(int i=0,lp=i+1,rp=i+1;i<num;i++){
        while(temp[lp].angle-temp[i].angle<Pi3-eps)lp++;
        if(lp==num)break;
        while(temp[rp].angle-temp[i].angle<5*Pi3+eps)rp++;
        ans=max(ans,min(temp[i].dist2,query(lp,rp-1)));
    }
}
int main() {
    //freopen("data.in","r",stdin);
    int n;
    init();
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%lf%lf",&po[i].x,&po[i].y);
    ans=0;
    for(int i=0;i<n;i++)
        solve(n,i);
    printf("%lf\n",sqrt(ans)/2.0);
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=4000;
const double eps=1e-8,inf=1e50,Pi=acos(-1.0);
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
} o,po[MAXN];
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b) {
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
struct data{
    double x,y,angle,dist2;
    data(){}
    data(double _x,double _y,double _a,double _d){
        x=_x;
        y=_y;
        angle=_a;
        dist2=_d;
    }
}temp[MAXN];
bool comp_angle(const data a,const data b) {
   int tmp=sign(a.angle-b.angle);
   if(tmp<0||(tmp==0&&a.dist2<b.dist2))return true;
   else return false;
}
double seg[MAXN*4];
void build(int now,int left,int right){
    if(left==right){
        seg[now]=temp[left].dist2;
        return;
    }
    else{
        int lc=now<<1,rc=lc|1,mid=(left+right)>>1;
        build(lc,left,mid);
        build(rc,mid+1,right);
        seg[now]=max(seg[lc],seg[rc]);
    }
}
double getmax(int now,int left,int right,int ll,int rr){
    if(ll>rr)return 0;
    if(left==ll&&right==rr){
        return seg[now];
    }
    int lc=now<<1,rc=lc|1,mid=(left+right)>>1;
    if(rr<=mid)return getmax(lc,left,mid,ll,rr);
    else if(ll>mid)return getmax(rc,mid+1,right,ll,rr);
    else{
        return max(getmax(lc,left,mid,ll,mid),getmax(rc,mid+1,right,mid+1,rr));
    }
}
double solve(int n,int center){
    double ans=0;
    int num=0;
    for(int i=0;i<n;i++){
        if(i==center)continue;
        temp[num++]=data(po[i].x,po[i].y,atan2(po[i].y-po[center].y,po[i].x-po[center].x),getdist2(po[i],po[center]));
    }
    sort(temp,temp+num,comp_angle);
    temp[num].angle=inf;
    build(1,0,num-1);
    for(int i=0;i<num;i++){
        int ll=i+1,rr=num,mid,lp,rp;
        while(ll<rr){
            mid=(ll+rr)>>1;
            if(temp[mid].angle-temp[i].angle>Pi/3.0-eps)
                rr=mid;
            else
                ll=mid+1;
        }
        if(rr==num)
            break;
        lp=rr;
        ll=i+1,rr=num;
        while(ll<rr){
            mid=(ll+rr)>>1;
            if(temp[mid].angle-temp[i].angle>5.0*Pi/3.0-eps)
                rr=mid;
            else
                ll=mid+1;
        }
        rp=rr-1;
        //printf("[%d,%d]\n",lp,rp);
        ans=max(ans,min(temp[i].dist2,getmax(1,0,num-1,lp,rp)));
    }
    return ans;
}
int main() {
    //freopen("data.in","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF) {
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&po[i].x,&po[i].y);
        double ans=0;
        for(int i=0;i<n;i++)
            ans=max(solve(n,i),ans);
        printf("%lf\n",sqrt(ans)/2.0);
    }
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=1000;
const double eps=1e-8,inf=1e50;
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
};
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b){
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
inline double getdist(point a,point b){
    return sqrt(getdist2(a,b));
}
double minlen(vector<point> tri){
    double len=inf;
    for(int i=0;i<3;i++){
        len=min(len,getdist2(tri[i],tri[(i+1)%3]));
    }
    return len;
}
bool comp_cod(const point a,const point b){
    return a.x<b.x||((sign(a.x-b.x)==0)&&a.y<b.y);
}
vector<point> convex_hull(vector<point> p){
    int i,j,top;
    sort(p.begin(),p.end(),comp_cod);
    vector<point> pg;
    for(i=top=0;i<p.size();i++)
    {
        while(top>1&&xmult(pg[top-2],pg[top-1],p[i])<-eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    j=top;
    for(i=p.size()-2;i>=0;i--)
    {
        while(top>j&&xmult(pg[top-2],pg[top-1],p[i])<-eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    pg.pop_back();
    return pg;
}
vector<point> make_tri(point a,point b,point c){
    vector<point> tri;
    tri.push_back(a);
    tri.push_back(b);
    tri.push_back(c);
    return tri;
}
vector<point> adjust_convex_hull(vector<point> p){
    int i,j,k,id;
    vector<point> pg;
    double mf;
    for(j=0;j<p.size();){
        i=j;
        pg.push_back(p[j++]);
        pg.push_back(p[j++]);
        while(j<p.size()&&xmult(p[i],p[i+1],p[j])==0){
            j++;
        }
        j--;
        if(xmult(p[i],p[i+1],p[j])==0&&j-i+1>3)
        {
            mf=0;id=-1;
            for(k=i+1;k<j;k++){
                double tmp=min(getdist2(p[i],p[k]),getdist2(p[k],p[j]));
                if(tmp>mf){
                    mf=tmp;
                    id=k;
                }
            }
            pg.pop_back();
            pg.push_back(p[id]);
            pg.push_back(p[j++]);
        }
        else{
            pg.push_back(p[j++]);
        }
    }
    return pg;
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        vector<point> p;
        point tmp;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&tmp.x,&tmp.y);
            p.push_back(tmp);
        }
        p=adjust_convex_hull(convex_hull(p));
        n=p.size();
        double ans=0;
        for(int i=0;i<n-2;i++){
            for(int j=i+1;j<n-1;j++){
                for(int k=j+1;k<n;k++){
                    ans=max(ans,minlen(make_tri(p[i],p[j],p[k])));
                }
            }
        }
        printf("%lf\n",sqrt(ans)/2.0);
    }
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=4000;
const double eps=1e-8,inf=1e50,Pi=acos(-1.0);
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
} o,po[MAXN];
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b) {
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
struct data{
    double x,y,angle,dist2;
    data(){}
    data(double _x,double _y,double _a,double _d){
        x=_x;
        y=_y;
        angle=_a;
        dist2=_d;
    }
}temp[MAXN];
bool comp_angle(const data a,const data b) {
   int tmp=sign(a.angle-b.angle);
   if(tmp<0||(tmp==0&&a.dist2<b.dist2))return true;
   else return false;
}
double seg[MAXN*4];
void build(int now,int left,int right){
    if(left==right){
        seg[now]=temp[left].dist2;
        return;
    }
    else{
        int lc=now<<1,rc=lc|1,mid=(left+right)>>1;
        build(lc,left,mid);
        build(rc,mid+1,right);
        seg[now]=max(seg[lc],seg[rc]);
    }
}
double getmax(int now,int left,int right,int ll,int rr){
    if(ll>rr)return 0;
    if(left==ll&&right==rr){
        return seg[now];
    }
    int lc=now<<1,rc=lc|1,mid=(left+right)>>1;
    if(rr<=mid)return getmax(lc,left,mid,ll,rr);
    else if(ll>mid)return getmax(rc,mid+1,right,ll,rr);
    else{
        return max(getmax(lc,left,mid,ll,mid),getmax(rc,mid+1,right,mid+1,rr));
    }
}
double ans;
void solve(int n,int center){
    int num=0;
    bool flag=false;
    for(int i=0;i<n;i++){
        if(i==center)continue;
        temp[num]=data(po[i].x,po[i].y,atan2(po[i].y-po[center].y,po[i].x-po[center].x),getdist2(po[i],po[center]));
        if(temp[num].dist2>ans)flag=true;
    }
    if(!flag)return;
    sort(temp,temp+num,comp_angle);
    temp[num].angle=inf;
    build(1,0,num-1);
    for(int i=0;i<num;i++){
        int ll=i+1,rr=num,mid,lp,rp;
        while(ll<rr){
            mid=(ll+rr)>>1;
            if(temp[mid].angle-temp[i].angle>Pi/3.0-eps)
                rr=mid;
            else
                ll=mid+1;
        }
        if(rr==num)
            break;
        lp=rr;
        ll=i+1,rr=num;
        while(ll<rr){
            mid=(ll+rr)>>1;
            if(temp[mid].angle-temp[i].angle>5.0*Pi/3.0+eps)
                rr=mid;
            else
                ll=mid+1;
        }
        rp=rr-1;
        ans=max(ans,min(temp[i].dist2,getmax(1,0,num-1,lp,rp)));
    }
}
int main() {
    //freopen("data.in","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF) {
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&po[i].x,&po[i].y);
        ans=0;
        for(int i=0;i<n;i++)
            solve(n,i);
        printf("%lf\n",sqrt(ans)/2.0);
    }
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=1000;
const double eps=1e-8,inf=1e50;
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
};
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b){
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
inline double getdist(point a,point b){
    return sqrt(getdist2(a,b));
}
double minlen(vector<point> tri){
    double len=inf;
    for(int i=0;i<3;i++){
        len=min(len,getdist2(tri[i],tri[(i+1)%3]));
    }
    return len;
}
bool comp_cod(const point a,const point b){
    return a.x<b.x||((sign(a.x-b.x)==0)&&a.y<b.y);
}
vector<point> adjust_convex_hull(vector<point> p,int first){
    int i,j,k,id;
    vector<point> pg;
    for(i=0;i<first;i++){
        pg.push_back(p[i]);
    }
    double mf;
    for(j=first;j<p.size();){
        i=j;
        pg.push_back(p[j++]);
        if(j==p.size())
            break;
        pg.push_back(p[j++]);
        while(j<p.size()&&sign(xmult(p[i],p[i+1],p[j]))==0){
            j++;
        }
        j--;
        if(sign(xmult(p[i],p[i+1],p[j]))==0&&j-i+1>3)
        {
            mf=0;id=-1;
            for(k=i+1;k<j;k++){
                double tmp=min(getdist2(p[i],p[k]),getdist2(p[k],p[j]));
                if(tmp>mf){
                    mf=tmp;
                    id=k;
                }
            }
            pg.pop_back();
            pg.push_back(p[id]);
            pg.push_back(p[j++]);
        }
        else if(j!=i+1){
            pg.push_back(p[j++]);
        }
        else
            j++;
    }
    return pg;
}
vector<point> convex_hull(vector<point> p){
    int i,j,top;
    sort(p.begin(),p.end(),comp_cod);
    vector<point> pg;
    for(i=top=0;i<p.size();i++)
    {
        while(top>1&&xmult(pg[top-2],pg[top-1],p[i])<-eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    pg=adjust_convex_hull(pg,0);
    j=top=pg.size();
    for(i=p.size()-2;i>=0;i--)
    {
        while(top>j&&xmult(pg[top-2],pg[top-1],p[i])<-eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    pg=adjust_convex_hull(pg,j-1);
    pg.pop_back();
    return pg;
}
vector<point> make_tri(point a,point b,point c){
    vector<point> tri;
    tri.push_back(a);
    tri.push_back(b);
    tri.push_back(c);
    return tri;
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        vector<point> p;
        point tmp;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&tmp.x,&tmp.y);
            p.push_back(tmp);
        }
        p=convex_hull(p);
        n=p.size();
        double ans=0;
        for(int i=0;i<n-2;i++){
            for(int j=i+1;j<n-1;j++){
                for(int k=j+1;k<n;k++){
                    ans=max(ans,minlen(make_tri(p[i],p[j],p[k])));
                }
            }
        }
        printf("%lf\n",sqrt(ans)/2.0);
    }
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=4000;
const double eps=1e-8,inf=1e50,Pi=acos(-1.0),Pi3=Pi/3.0;
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
} o,po[MAXN];
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b) {
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
struct data{
    double angle,dist2;
    data(){}
    data(double _a,double _d){
        angle=_a;
        dist2=_d;
    }
}temp[MAXN];
bool comp_angle(const data a,const data b) {
   int tmp=sign(a.angle-b.angle);
   if(tmp<0||(tmp==0&&a.dist2<b.dist2))return true;
   else return false;
}
double st[20][MAXN];
int ln[MAXN];
void init(){
    for(int i=2,j=0,temp=0;j<MAXN;i<<=1,temp++){
        for(;j<i&&j<MAXN;j++){
            ln[j]=temp;
        }
    }
}
void init_rmq(int n){
    int i,j,k,sk;
    for(i=0;i<n;i++)st[0][i]=temp[i].dist2;
    for(i=1,k=2;k<n;i++,k<<=1){
        for(j=0,sk=(k>>1);j+k-1<=n;++j,++sk){
            st[i][j]=st[i-1][j];
            if(sk<n&&st[i][j]<st[i-1][sk])
                st[i][j]=st[i-1][sk];
        }
    }
}
double query(int x,int y){
    if(x>y)return 0.0;
    int b=ln[y-x+1];
    return max(st[b][x],st[b][y-(1<<b)+1]);
}
double ans;
void solve(int n,int center){
    int num=0;
    for(int i=0;i<n;i++){
        if(i==center)continue;
        temp[num]=data(atan2(po[i].y-po[center].y,po[i].x-po[center].x),getdist2(po[i],po[center]));
        if(temp[num].dist2>ans){
            num++;
        }
    }
    if(!num)return;
    sort(temp,temp+num,comp_angle);
    temp[num].angle=inf;
    init_rmq(num);
    for(int i=0,lp=i+1,rp=i+1;i<num;i++){
        while(temp[lp].angle-temp[i].angle<Pi3-eps)lp++;
        if(lp==num)break;
        while(temp[rp].angle-temp[i].angle<5*Pi3+eps)rp++;
        ans=max(ans,min(temp[i].dist2,query(lp,rp-1)));
    }
}
int main() {
    //freopen("data.in","r",stdin);
    int n;
    init();
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%lf%lf",&po[i].x,&po[i].y);
    ans=0;
    for(int i=0;i<n;i++)
        solve(n,i);
    printf("%lf\n",sqrt(ans)/2.0);
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=1000;
const double eps=1e-8,inf=1e50;
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
};
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b){
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
inline double getdist(point a,point b){
    return sqrt(getdist2(a,b));
}
double minlen(vector<point> tri){
    double len=inf;
    for(int i=0;i<3;i++){
        len=min(len,getdist2(tri[i],tri[(i+1)%3]));
    }
    return len;
}
bool comp_cod(const point a,const point b){
    return a.x<b.x||((sign(a.x-b.x)==0)&&a.y<b.y);
}
vector<point> convex_hull(vector<point> p){
    int i,j,top;
    sort(p.begin(),p.end(),comp_cod);
    vector<point> pg;
    for(i=top=0;i<p.size();i++)
    {
        while(top>1&&xmult(pg[top-2],pg[top-1],p[i])<eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    j=top;
    for(i=p.size()-2;i>=0;i--)
    {
        while(top>j&&xmult(pg[top-2],pg[top-1],p[i])<eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    pg.pop_back();
    return pg;
}
vector<point> make_tri(point a,point b,point c){
    vector<point> tri;
    tri.push_back(a);
    tri.push_back(b);
    tri.push_back(c);
    return tri;
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        vector<point> p;
        point tmp;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&tmp.x,&tmp.y);
            p.push_back(tmp);
        }
        p=convex_hull(p);
        n=p.size();
        double ans=0;
        for(int i=0;i<n-2;i++){
            for(int j=i+1;j<n-1;j++){
                for(int k=j+1;k<n;k++){
                    ans=max(ans,minlen(make_tri(p[i],p[j],p[k])));
                }
            }
        }
        printf("%lf",sqrt(ans)/2.0);
    }
    return 0;
}


#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)>(b))?(b):(a))
#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //��ź���
using namespace std;
const int MAXN=1000;
const double eps=1e-8,inf=1e50;
struct point {
    double x,y;
    point() {}
    point(double _x,double _y) {
        x=_x;
        y=_y;
    }
};
inline double xmult(point o,point a,point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
inline double xmult(double x1,double y1,double x2,double y2) {
    return x1*y2-x2*y1;
}
inline double getdist2(point a,point b){
    double dx=a.x-b.x,dy=a.y-b.y;
    return dx*dx+dy*dy;
}
inline double getdist(point a,point b){
    return sqrt(getdist2(a,b));
}
double minlen(vector<point> tri){
    double len=inf;
    for(int i=0;i<3;i++){
        len=min(len,getdist2(tri[i],tri[(i+1)%3]));
    }
    return len;
}
bool comp_cod(const point a,const point b){
    return a.x<b.x||((sign(a.x-b.x)==0)&&a.y<b.y);
}
vector<point> convex_hull(vector<point> p){
    int i,j,top;
    sort(p.begin(),p.end(),comp_cod);
    vector<point> pg;
    for(i=top=0;i<p.size();i++)
    {
        while(top>1&&xmult(pg[top-2],pg[top-1],p[i])<-eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    j=top;
    for(i=p.size()-2;i>=0;i--)
    {
        while(top>j&&xmult(pg[top-2],pg[top-1],p[i])<-eps)
            pg.pop_back(),top--;
        pg.push_back(p[i]),top++;
    }
    pg.pop_back();
    return pg;
}
vector<point> make_tri(point a,point b,point c){
    vector<point> tri;
    tri.push_back(a);
    tri.push_back(b);
    tri.push_back(c);
    return tri;
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        vector<point> p;
        point tmp;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&tmp.x,&tmp.y);
            p.push_back(tmp);
        }
        p=convex_hull(p);
        n=p.size();
        double ans=0;
        for(int i=0;i<n-2;i++){
            for(int j=i+1;j<n-1;j++){
                for(int k=j+1;k<n;k++){
                    ans=max(ans,minlen(make_tri(p[i],p[j],p[k])));
                }
            }
        }
        printf("%lf\n",sqrt(ans)/2.0);
    }
    return 0;
}