#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define Pr pair<ll,ll>
#define Tp tuple<ll,ll,ll>
using Graph = vector<vector<int>>;

ll mod = 998244353;

//Unionfind
struct unionfind {
	//自身が親であれば、その集合に属する頂点数に-1を掛けたもの
	//そうでなければ親のid
	  vector<int> r;
	  unionfind(int N) {
		    r = vector<int>(N, -1);
	  }
	  int root(int x) {
		    if (r[x] < 0) return x;
		    return r[x] = root(r[x]);
	  }
	  bool unite(int x, int y) {
		    x = root(x);
		    y = root(y);
		    if (x == y) return false;
		    if (r[x] > r[y]) swap(x, y);
		    r[x] += r[y];
		    r[y] = x;
		    return true;
	  }
	  int size(int x) {
		    return max(-r[root(x)],0);
	  }
  
  // 2つのデータx, yが属する木が同じならtrueを返す
    bool same(int x, int y) { 
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }
};
  

int main() {
    ll N; cin >> N;
    //main関数内で 
    unionfind pts(N+2);
  //などと宣言し  friends.unite(a,b);
  //のように使う
    ll x[N],y[N];
    rep(i,N){
        cin >> x[i] >> y[i];
    }
    vector<tuple<double,int,int>> dist;
    rep(i,N){
        dist.push_back(make_tuple(100-y[i],i,N));
        dist.push_back(make_tuple(y[i]+100,i,N+1));
    }
    rep(i,N){
        for(int j=1+i;j<N;j++){
            double d = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
            dist.push_back(make_tuple(d,i,j));
        }
    }
    sort(dist.begin(),dist.end());
    double ans = 0;
    for(auto q:dist){
        double s = get<0>(q);
        int i = get<1>(q); int j = get<2>(q);
        pts.unite(i,j);
        if(pts.same(N,N+1)){
            ans = s/2; break;
        }
    }
    cout << setprecision(15) << ans << endl;
}

#include <bits/stdc++.h>

using namespace std;
template <typename T> using triple = std::tuple<T, T, T>;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.precision(17);
  
  int n;
  cin >> n;
  vector<int> X(n), Y(n);
  for(int i = 0; i < n; i++) {
    cin >> X[i] >> Y[i];
  }

  vector<triple<int>> edges;
  int st = n, en = n + 1;

  for(int i = 0; i < n; i++) {
    for(int j = i + 1; j < n; j++) {
      int dx = X[i] - X[j], dy = Y[i] - Y[j];
      int d = dx * dx + dy * dy;
      edges.emplace_back(d, i, j);
    }
    int top = Y[i] + 100, bottom = 100 - Y[i];
    top *= top, bottom *= bottom;
    edges.emplace_back(top, st, i);
    edges.emplace_back(bottom, i, en);
  }
  sort(edges.begin(), edges.end());
  
  vector<int> p(n + 2), si(n + 2, 1);
  iota(p.begin(), p.end(), 0);

  auto trace = [&](int u) {
    while(u != p[u]) u = p[u] = p[p[u]] = p[p[p[u]]] = p[p[p[p[u]]]];
    return u;
  };

  auto unite = [&](int u, int v) {
    if((u = trace(u)) != (v = trace(v))) {
      if(si[u] > si[v]) swap(u, v);
      p[u] = v;
      si[v] += si[u];
    }
  };

  for(auto [d, x, y] : edges) {
    unite(x, y);
    if(trace(st) == trace(en)) {
      cout << sqrt(d) / 2 << '\n';
      return 0;
    }
  }
  assert(false);
}
