#include <bits/stdc++.h>
using namespace std;
const int N = 5005;
struct point {
  double x, y, z;
  point(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
};
double dist(const point& a, const point& b) {
  return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) +
              (a.z - b.z) * (a.z - b.z));
}
struct edge {
  int p;
  double t;
  edge(int p, double t) : p(p), t(t) {}
  bool operator<(const edge& e) const { return t > e.t; }
};
int n, size;
point p[N];
set<double, greater<double> > frame[N];
double dijkstra() {
  priority_queue<edge> pq;
  pq.push(edge(0, 0));
  double mn = HUGE_VAL;
  while (!pq.empty()) {
    edge e = pq.top();
    pq.pop();
    if (e.t > mn) break;
    for (int i = 0; i < n; ++i) {
      if (e.p == i) continue;
      double d = dist(p[i], p[e.p]);
      double nt = e.t + d;
      set<double, greater<double> >::iterator it =
          frame[i].lower_bound(e.t + d);
      if (it == frame[i].end()) {
        frame[i].insert(nt);
        pq.push(edge(i, nt));
      } else {
        double f = *it;
        if (!(nt - d <= f + 1e-7 && f - 1e-7 <= nt)) {
          frame[i].insert(nt);
          pq.push(edge(i, nt));
        } else {
          double x = (nt + f) / 2;
          mn = min(mn, x);
        }
      }
    }
  }
  return mn;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(12);
  cout << fixed;
  cin >> n;
  for (int i = 0; i < n; ++i) {
    cin >> p[i].x >> p[i].y >> p[i].z;
  }
  size = n;
  cout << dijkstra() << endl;
}
