#include <bits/stdc++.h>
using namespace std;
int x[5000], y[5000], z[5000];
double dist[5000][5000];
inline double SQR(double a) { return a * a; }
inline double SQR_DIST(int i, int j) {
  return SQR(x[i] - x[j]) + SQR(y[i] - y[j]) + SQR(z[i] - z[j]);
}
int main() {
  int n;
  cin >> n;
  for (int i = (int)(0); i < (int)(n); i++) cin >> x[i] >> y[i] >> z[i];
  for (int i = (int)(0); i < (int)(n); i++) {
    dist[i][i] = 0.0;
    for (int j = (int)(0); j < (int)(i); j++) {
      dist[i][j] = dist[j][i] = sqrt(SQR_DIST(i, j));
    }
  }
  priority_queue<pair<double, pair<int, int> >,
                 vector<pair<double, pair<int, int> > >,
                 greater<pair<double, pair<int, int> > > >
      que;
  que.push(make_pair(0.0, make_pair(-1, 0)));
  bool already[5000];
  memset(already, 0, sizeof(already));
  double arrivedTime[5000];
  while (!que.empty()) {
    pair<double, pair<int, int> > now = que.top();
    que.pop();
    if (now.second.second == -1) {
      printf("%.10lf\n", now.first);
      break;
    }
    already[now.second.second] = true;
    arrivedTime[now.second.second] = now.first;
    double HitTime = -1;
    for (int i = (int)(0); i < (int)(n); i++)
      if (i != now.second.first && i != now.second.second) {
        if (already[i]) {
          double sub = now.first - arrivedTime[i];
          double rem = dist[i][now.second.second] - sub;
          if (HitTime < -1.0e-10 || HitTime > 1.0e-10 && HitTime > rem / 2)
            HitTime = rem / 2;
        } else {
          que.push(make_pair(now.first + dist[now.second.second][i],
                             make_pair(now.second.second, i)));
        }
      }
    if (HitTime > -1.0e-10)
      que.push(make_pair(HitTime + now.first, make_pair(-1, -1)));
  }
  return 0;
}
