#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
using ll = long long;

struct UnionFind {
    UnionFind(int n) : p(n, -1) {}
    int root(int u) {
        return p[u] < 0 ? u : p[u] = root(p[u]);
    }
    int size(int u) {
        return -p[root(u)];
    }
    bool same(int u, int v) {
        return root(u) == root(v);
    }
    void unite(int u, int v) {
        u = root(u);
        v = root(v);
        if (u == v) return;
        if (p[u] > p[v]) swap(u, v);
        p[u] += p[v];
        p[v] = u;
    }
    vector<int> p;
};

template <class T, class F>
T LowerBound(T i0, T i1, F f) {
    while (i0 < i1) {
        T i = i0 + (i1 - i0) / 2;
        if (f(i)) i1 = i; else i0 = i + 1;
    }
    return i0;
}

struct P {
    int x, y;
};

int main() {
    int n;
    cin >> n;

    vector<P> p(n);
    for (int i = 0; i < n; i++) {
        int x, y;
        cin >> x >> y;

        p[i] = { x, y };
    }

    auto r2 = LowerBound<int>(2, 40001, [&](auto r2) {
        UnionFind uf(n + 2);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                int x = p[i].x - p[j].x;
                int y = p[i].y - p[j].y;
                if (x * x + y * y < r2) uf.unite(i, j);
            }
            for (int h = 0; h < 2; h++) {
                int y = p[i].y - 100 * (h == 0 ? 1 : -1);
                if (y * y < r2) uf.unite(i, n + h);
            }
        }
        return uf.same(n, n + 1);
    }) - 1;

    printf("%.9f\n", sqrt(r2) * 0.5);

    return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
#include <utility>
#include <tuple>
#include <functional>
#include <bitset>
#include <cassert>
#include <complex>
#include <stdio.h>
#include <time.h>
#include <numeric>
#include <random>
#include <unordered_map>
#include <unordered_set>
#define all(a) a.begin(),a.end()
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define pb push_back
#define debug(x) cerr << __LINE__ << ' ' << #x << ':' << (x) << '\n'
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> P;
typedef complex<ld> com;
template<class T> using prique = priority_queue<T, vector<T>, greater<T>>;
constexpr int inf = 1000000010;
constexpr ll INF = 1000000000000000010;
constexpr int mod1e9 = 1000000007;
constexpr int mod998 = 998244353;
constexpr ld eps = 1e-12;
constexpr ld pi = 3.141592653589793238;
constexpr ll ten(int n) { return n ? 10 * ten(n - 1) : 1; };
int dx[] = { 1,0,-1,0,1,1,-1,-1 }; int dy[] = { 0,1,0,-1,1,-1,1,-1 };
void fail() { cout << "-1\n"; exit(0); } void no() { cout << "No\n"; exit(0); }
template<class T, class U> inline bool chmax(T &a, const U &b) { if (a < b) { a = b; return true; } return false; }
template<class T, class U> inline bool chmin(T &a, const U &b) { if (a > b) { a = b; return true; } return false; }
template<class T> istream &operator >> (istream &s, vector<T> &v) { for (auto &e : v) s >> e; return s; }
template<class T> ostream &operator << (ostream &s, const vector<T> &v) { for (auto &e : v) s << e << ' '; return s; }

struct fastio {
	fastio() {
		cin.tie(0); cout.tie(0);
		ios::sync_with_stdio(false);
		cout << fixed << setprecision(20);
		cerr << fixed << setprecision(20);
	}
}fastio_;

class unionfind {
	vector<int> par;
	vector<int> sz;
public:
	unionfind(int n) {
		par = vector<int>(n);
		for (int i = 0; i < n; i++) par[i] = i;
		sz = vector<int>(n, 1);
	}
	int find(int x) {
		if (par[x] == x) return x;
		else return par[x] = find(par[x]);
	}
	int size(int x) { return sz[find(x)]; }
	bool same(int x, int y) { return find(x) == find(y); }
	void unite(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) return;
		if (sz[x] < sz[y]) {
			par[x] = y;
			sz[y] += sz[x];
		}
		else {
			par[y] = x;
			sz[x] += sz[y];
		}
	}
};

bool comp(pair<P, ld> a, pair<P, ld> b) {
	return a.second < b.second;
}

int main() {
	int n;
	cin >> n;
	vector<ld> x(n), y(n);
	rep(i, n) cin >> x[i] >> y[i];
	unionfind uni(n + 2);
	vector<pair<P, ld>> p;
	rep(i, n) {
		rep(j, i) {
			p.pb({ {i,j},sqrtl((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])) });
		}
	}
	rep(i, n) p.pb({ {n,i},100 - y[i] });
	rep(i, n) p.pb({ { n + 1,i }, y[i] + 100 });
	p.pb({ {n,n + 1},200 });
	sort(all(p), comp);
	for (auto q : p) {
		int x = q.first.first;
		int y = q.first.second;
		uni.unite(x, y);
		if (uni.same(n, n + 1)) {
			cout << q.second / 2 << '\n';
			return 0;
		}
	}
}