//#include <atcoder/all>
#include <bits/stdc++.h>
#include <cassert>
#include <numeric>
using namespace std;
//using namespace atcoder;
typedef  long long LONG;
const int MOD = 1000000007;



int gcd(int x, int y) {
	if (x % y == 0) {
		return y;
	}
	else {
		return gcd(y, x % y);
		//x%y==0でないときはユーグリットの互除法を使って再帰的に関数を呼び出す。
	}
}
LONG pow2(long long x, long long n) {
	long long ret = 1;
	while (n > 0) {
		if (n & 1) ret = ret * x % MOD;  // n の最下位bitが 1 ならば x^(2^i) をかける
		x = x * x % MOD;
		n >>= 1;  // n を1bit 左にずらす
	}
	return (int)ret;
}
void printVector(const vector<int>& vec) {
	for (int value : vec) {
		cout << value << " ";
	}
	cout << endl;
}
LONG t(LONG N,LONG i) {
	return N - abs(i);
}
int count(vector<int>&a, int s) {
	int result = 0;
	for (int i = 0; i < a.size(); i++) {
		if (a[i] == s) {
			result++;
		}
	}
	return result;
}

LONG kaizyo(int N) {
	LONG result = 1;
	LONG mod = 998244353;

	for (LONG i = 2; i <= N; i++) {
		result *= i;
		result = result % mod;
	}
	return result;
}
class Point {
public:
	int x;
	int y;
};
LONG stock[3500][3500];
LONG test(int N, int task) {
	LONG mod = 998244353;
	if (N < task)return 0;
	if (N < 0)return 0;
	if (task == 0) {
		if (N == 0) {
			return 1;
		}
		else {
			return 0;
		}

	}


	if (stock[N][task] > 0)return stock[N][task];
	stock[N][task] =( test(N - 1, task - 1) + test(N, task * 2)) % mod;

	return stock[N][task]%mod ;
}
class DP {
public:
	DP() {

	}
	DP(int a, int b) {
		other = a;
		path = b;

	}
	int other;
	int path;
};

void dp(vector<vector<DP>>& list, vector<int> &able, int pos,int limit) {
	for (int i = 0; i < list[pos].size(); i++) {
		if (list[pos][i].path <= limit) {
			if (able[list[pos][i].other] == 0) {
				able[list[pos][i].other] = 1;
				dp(list, able, list[pos][i].other, limit);
			}
		}
	}
}
int main() {

	LONG N;
	cin >> N;
	vector<Point>P(N);
	for (int i = 0; i < N; i++) {
		cin >>P[i].x>>P[i].y;
	}
	vector<vector<DP>>d(N+2, vector<DP>(0));

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < i; j++) {

			int r = (P[i].x - P[j].x)*(P[i].x - P[j].x) + (P[i].y - P[j].y)*(P[i].y - P[j].y);
			if (r < 40000) {
				d[i+2].push_back(DP(j+2, r));
				d[j+2].push_back(DP(i+2, r));
			}
		}
	}
	for (int i = 0; i < N; i++) {
		d[i+2].push_back(DP(0, (100-P[i].y)* (100 - P[i].y)));
		d[0].push_back(DP(i+2, (100 - P[i].y)*(100-P[i].y)));
	}
	for (int i = 0; i < N; i++) {
		d[i + 2].push_back(DP(1, (-100 - P[i].y)* (-100 - P[i].y)));
		d[1].push_back(DP(i + 2, (-100 - P[i].y)* (-100 - P[i].y)));
	}
	d[0].push_back(DP(1, 40000));
	d[1].push_back(DP(0, 40000));
	int max = 40000;
	int min = 0;
	int mid = (max) / 2;
	while (max - min > 1) {
		bool frag = false;
		vector<int> able(N + 2, 0 );//未到達は0、到達は1
		able[0] = 1;
		dp(d, able, 0, mid);
		if (able[1] == 1) {
			max = mid;
			mid = (max + min) / 2;
		}else{
			min = mid;
			mid = (max + min) / 2;
		}
//		cout << max<<"\t" << min << "\t" << mid << "\n";
	}
	cout << std::fixed << std::setprecision(15) << sqrt(mid+1)/2.0;


	
	return 0;
}
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ch() getchar()
#define pc(x) putchar(x)
using namespace std;
template<typename T>void read(T&x){
	char c;int f;
	for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
	for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>void write(T x){
	static char q[64];int cnt=0;
	if(x==0)return pc('0'),void();
	if(x<0)pc('-'),x=-x;
	while(x)q[cnt++]=x%10,x/=10;
	while(cnt--)pc(q[cnt]+'0');
}
const int maxn=105;
struct Node{
	int v,w;
	Node(int v=0,int w=0):
		v(v),w(w){}
	bool operator < (const Node o)const{
		return w<o.w;
	}
}hp[maxn*maxn*2];
int sz;
void push(Node x){
	int no=++sz;
	while(no>1&&x<hp[no>>1])
		hp[no]=hp[no>>1],no>>=1;
	hp[no]=x;
}
void pop(void){
	swap(hp[1],hp[sz--]);
	int no=1,nt=2;Node x=hp[1];
	while(nt<=sz){
		if((nt|1)<=sz&&hp[nt|1]<hp[nt])nt|=1;
		if(hp[nt]<x)hp[no]=hp[nt];else break;
		no=nt;nt<<=1;
	}
	hp[no]=x;
}
int top(void){
	return hp[1].v;
}
struct Edge{
	int v,w,nt;
	Edge(int v=0,int w=0,int nt=0):
		v(v),w(w),nt(nt){}
}e[maxn*maxn*2];
int hd[maxn],num;
void qwq(int u,int v,int w){
	e[++num]=Edge(v,w,hd[u]),hd[u]=num;
}
void qvq(int u,int v,int w){
	qwq(u,v,w);qwq(v,u,w);
}
int sq(int x){
	return x*x;
}
int dis[maxn],vis[maxn],x[maxn],y[maxn];
int main(){
	int n;read(n);
	int S=n+1,T=S+1;
	qvq(S,T,sq(200));
	for(int i=1;i<=n;++i){
		read(x[i]),read(y[i]);
		qvq(S,i,sq(y[i]+100));
		qvq(i,T,sq(100-y[i]));
		for(int j=1;j<i;++j){
			qvq(i,j,sq(x[i]-x[j])+sq(y[i]-y[j]));
		}
	}
	memset(dis,0x3f,sizeof dis);
	push(Node(S,dis[S]=0));
	while(sz){
		int u=top();pop();
		if(vis[u])continue;vis[u]=true;
		for(int i=hd[u];i;i=e[i].nt){
			int v=e[i].v,w=max(dis[u],e[i].w);
			if(dis[v]>w)push(Node(v,dis[v]=w));
		}
	}
	printf("%.20f\n",sqrt(dis[T])/2.0);
	return 0;
}
/*
所以，永远不要问丧钟为谁而鸣，它为你而鸣。
*/
