#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
#define all(x) x.begin(),x.end()
#define STRINGIFY(n) #n
#define TOSTRING(n) STRINGIFY(n)
#define PREFIX "#" TOSTRING(__LINE__) "| "
#define debug(x) \
{ \
  std::cout << PREFIX << #x << " = " << x << std::endl; \
}

std::ostream& output_indent(std::ostream& os, int ind) {
  for(int i = 0; i < ind; i++) os << " ";
  return os;
}

template<class S, class T> std::ostream& operator<<(std::ostream& os, const std::pair<S, T>& p);
template<class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v);

template<class S, class T> std::ostream& operator<<(std::ostream& os, const std::pair<S, T>& p) {
  return (os << "(" << p.first << ", " << p.second << ")");
}
template<class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
  os << "[";
  for(int i = 0;i < v.size();i++) os << v[i] << ", ";
  return (os << "]");
}

template<class T>
static inline std::vector<T> ndvec(size_t&& n, T val) { return std::vector<T>(n, std::forward<T>(val)); }
template<class... Tail>
static inline auto ndvec(size_t&& n, Tail&&... tail) {
  return std::vector<decltype(ndvec(std::forward<Tail>(tail)...))>(n, ndvec(std::forward<Tail>(tail)...));
}
template<class Cond> struct chain {
  Cond cond; chain(Cond cond) : cond(cond) {}
  template<class T> bool operator()(T& a, const T& b) const { if(cond(a, b)) { a = b; return true; } return false; }
};
template<class Cond> chain<Cond> make_chain(Cond cond) { return chain<Cond>(cond); }

#include <vector>
#include <tuple>

struct union_find {
  std::vector<int> par;
  union_find(int N): par(N, -1) {}
  int root(int x) {
    return par[x] < 0 ? x : par[x] = root(par[x]);
  }
  std::tuple<int, int> unite(int x, int y) {
    x = root(x);
    y = root(y);
    if(x == y) return { -1, -1 };
    if(par[x] > par[y]) std::swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return { x, y };
  }
  int size(int x) {
    return -par[root(x)];
  }
};

using ld = long double;
int main() {
  i64 N;
  cin >> N;
  vector<ld> X(N), Y(N);
  rep(i,0,N) {
    cin >> X[i] >> Y[i];
  }

  rep(i,0,N) {
    X.push_back(X[i]);
    Y.push_back(100);
  }
  rep(i,0,N) {
    X.push_back(X[i]);
    Y.push_back(-100);
  }

  ld ok = 0;
  ld ng = 150;
  rep(t,0,60) {
    ld mid = (ok + ng) / 2;

    union_find uf(3 * N + 2);
    rep(i,0,3*N) rep(j,i+1,3*N) {
      ld dx = (X[i] - X[j]);
      ld dy = (Y[i] - Y[j]);
      ld dist = sqrt(dx * dx + dy * dy) / 2;
      if(dist < mid) {
        uf.unite(i, j);
      }
    }
    i64 s = 3 * N;
    i64 T = 3 * N + 1;
    rep(i,N,2*N) {
      uf.unite(s,i);
    }
    rep(i,2*N,3*N) {
      uf.unite(T,i);
    }
    if(uf.root(s) == uf.root(T)) {
      ng = mid;
    }
    else {
      ok = mid;
    }
  }
  cout << fixed << setprecision(10) << ok << endl;
}

#pragma GCC optimize("Ofast", "unroll-loops")
#pragma GCC target("avx2")

#include <bits/stdc++.h>

struct node{
    int x, y;
    bool isLine;
    node() {}
    node(int x, int y) : x(x), y(y), isLine(false) {}
    node(int y) : x(0), y(y), isLine(true) {}
};

double dist(node n1, node n2){
    if (n1.isLine || n2.isLine)
        return std::abs(n1.y - n2.y);
    int dx = n1.x - n2.x;
    int dy = n1.y - n2.y;
    return std::sqrt((double)(dx * dx + dy * dy));
}

int N;
std::vector<node> nodes;

void input(void){
    std::cin >> N;
    nodes.resize(N + 2);
    nodes[0] = node(100);
    nodes[N + 1] = node(-100);
    for (int i = 1; i <= N; ++i){
        int x, y;
        std::cin >> x >> y;
        nodes[i] = node(x, y);
    }
}

double solve(void){
    // d[i] := node 0とnode iを連結にするのに必要なrのmin
    std::vector<double> d(N + 2, 200.0);
    std::queue<std::pair<double, int>> q;
    d[0] = 0.0;
    q.emplace(0.0, 0);
    while (!q.empty()){
        std::pair<double, int> p = q.front();
        q.pop();
        int v = p.second;
        if (d[v] > p.first) continue;
        for (int i = 0; i < N + 2; ++i)
        if (i != v){
            double distance = dist(nodes[v], nodes[i]);
            double tmp = std::max(p.first, distance);
            if (d[i] > tmp){
                d[i] = tmp;
                q.emplace(tmp, i);
            }
        }
    }
    return d[N + 1] / 2;
}

int main(void){
    input();
    std::cout << std::setprecision(15) << solve() << std::endl;
    return 0;
}