#include<cstdio>
#include<cmath>

#define db double
#define ri register int 

#define sqr(x) ((x)*(x))
#define eps 1e-6

using namespace std;

const int MAXN=100+10;

int n;
int x[MAXN],y[MAXN];
db sdis(int i,int j){return sqr(x[i]-x[j])+sqr(y[i]-y[j]);}

int fa[MAXN];
int get_fa(int u){return u==fa[u]?u:fa[u]=get_fa(fa[u]);}
void merge(int u,int v){fa[get_fa(u)]=get_fa(v);}
bool check(db r)
{
	for(ri i=0;i<=n+1;++i)fa[i]=i;
	for(ri i=1;i<=n;++i)
		for(ri j=i+1;j<=n;++j)if(sdis(i,j)<sqr(r*2))
			merge(i,j);
	for(ri i=1;i<=n;++i)if(sqr(100-y[i])<sqr(r*2))merge(i,0);
	for(ri i=1;i<=n;++i)if(sqr(y[i]+100)<sqr(r*2))merge(i,n+1);
	return get_fa(0)!=get_fa(n+1);
}

int main()
{
//	freopen("1.in","r",stdin);
	
	scanf("%d",&n);
	for(ri i=1;i<=n;++i)scanf("%d %d",&x[i],&y[i]);
	
	db l=0,r=100,m;
	while(r-l>eps)
	{
		m=(l+r)/2;
		if(check(m))l=m;
		else r=m;
	}
	printf("%lf\n",l);
	
	return 0;
}
//
//  main.cpp
//

#include <algorithm>
#include <array>
#include <assert.h>
#include <complex>
#include <iomanip>
#include <iostream>
#include <limits>
#include <inttypes.h>
#include <map>
#include <math.h>
#include <memory>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// #include <atcoder/dsu>
// using namespace atcoder;
// using mint = modint1000000007;
// using mint = modint998244353;
// using mint = modint;

using namespace std;

using ll = int64_t;
using ull = uint64_t;

[[maybe_unused]] constexpr ll LL_MAX = numeric_limits<ll>::max();
[[maybe_unused]] constexpr ll LL_MIN = numeric_limits<ll>::min();
[[maybe_unused]] constexpr ull ULL_MAX = numeric_limits<ull>::max();

#define rep(i, a, b) for (ll i = (a); i < (b); i++)
#define rrep(i, a, b) for (ll i = (a)-1; i >= (b); i--)

template<typename T>
void chmin(T& x, T y) {
	x = min(x, y);
}

template<typename T>
void chmax(T& x, T y) {
	x = max(x, y);
}

ll csum(ll x, ll y) {
	if (x > 0 && y > 0 && x > LL_MAX - y) {
		return LL_MAX;
	}
	if (x < 0 && y < 0 && x < LL_MIN - y) {
		return LL_MIN;
	}
	return x + y;
}

ll readi() {
	ll ret;
	scanf("%" PRId64 "", &ret);
	return ret;
}

vector<ll> readvi(ll n) {
	vector<ll> ret(n);
	rep(i, 0, n) { ret[i] = readi(); }
	return ret;
}

double readf() {
	double ret;
	scanf("%lf", &ret);
	return ret;
}

string reads() {
	string s;
	cin >> s;
	return s;
}

void writei(ll x) {
	printf("%" PRId64 "\n", x);
}

void writevi(const vector<ll>& xs) {
    rep(i,0,xs.size()) {
        if (i < xs.size() - 1) {
            printf("%" PRId64 " ", xs[i]);
        } else {
            printf("%" PRId64 "\n", xs[i]);
        }
    }
}

void writes(const string& s) {
	cout << s.c_str() << endl;
}

void writef(double x) {
	printf("%.10f\n", x);
}

template<typename T>
vector<T> make_vec_nd(T init, ll size) {
	return vector<T>(size, init);
}
template<typename T, typename... Args>
auto make_vec_nd(T init, ll size, Args... rest) {
	auto inner = make_vec_nd(init, rest...);
	return vector<decltype(inner)>(size, inner);
}

struct UnionFind {
	vector<size_t> parent;
	vector<size_t> rank;
	size_t find_parent(size_t x) {
		if (parent[x] == x) {
			return x;
		} else {
			parent[x] = find_parent(parent[x]);
			return parent[x];
		}
	}
	explicit UnionFind(size_t size) {
		parent.resize(size);
		rank.resize(size);
		for (size_t i = 0; i < size; i++) {
			parent[i] = i;
			rank[i] = 0;
		}
	}
	virtual ~UnionFind() {}
	void unite(size_t x, size_t y) {
		size_t px = find_parent(x);
		size_t py = find_parent(y);
		if (px == py) {
			return;
		}
		if (rank[px] < rank[py]) {
			parent[px] = py;
		} else if (rank[px] > rank[py]) {
			parent[py] = px;
		} else {	// rank[px] == rank[py]
			parent[py] = px;
			rank[px]++;
		}
	}
	bool is_same(size_t x, size_t y) {
		return find_parent(x) == find_parent(y);
	}
	unordered_map<size_t, set<size_t>> create_map_parent_to_elements() {
		unordered_map<size_t, set<size_t>> ans;
		for (size_t i = 0; i < parent.size(); i++) {
			ans[find_parent(i)].insert(i);
		}
		return ans;
	}
};

struct P {
	double x;
	double y;
	double dist(const P& rhs) const {
		double sq = (x - rhs.x) * (x - rhs.x) + (y - rhs.y) * (y - rhs.y);
		return sqrt(sq);
	}
};

int main() {
	ll N = readi();
	vector<P> pts(N);
	rep(i,0,N) {
		pts[i].x = readi();
		pts[i].y = readi();
	}
	double good = 0.0;
	double bad = 100.0;
	while (bad - good > 1.0e-5) {
		double mid = (good + bad) / 2;
		UnionFind tree(N + 2);
		rep(i,0,N) {
			P a = pts[i];
			rep(j,i+1,N) {
				P b = pts[j];
				if (a.dist(b) < 2*mid) {
					tree.unite(i, j);
				}
			}
			if (a.y + 100 < 2*mid) {
				tree.unite(i, N);
			}
			if (100 - a.y < 2*mid) {
				tree.unite(i, N+1);
			}
		}
		if (tree.is_same(N, N+1)) {
			bad = mid;
		} else {
			good = mid;
		}
	}
	writef(good);
}
