#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cassert>
#include<climits>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define IINF (INT_MAX)
#define EPS (1e-10)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define MAX 31
#define pow2(a) ((a)*(a))

using namespace std;

class Point
{
  public:
  double x,y,z;

  Point(double x = -IINF,double y = -IINF,double z=-IINF): x(x),y(y),z(z){}

  Point operator + (Point p){return Point(x+p.x,y+p.y,z+p.z);}
  Point operator - (Point p){return Point(x-p.x,y-p.y,z-p.z);}
  Point operator * (double a){return Point(a*x,a*y,a*z);}
  Point operator / (double a){return Point(x/a,y/a,z/a);}

  bool operator == (const Point& p)const
  {
    return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS && fabs(z-p.z) < EPS;
  }

};

typedef Point Vector;

int V;
Point ps[MAX];

inline double dist(Point a,Point b)
{
  return sqrt(pow2(a.x-b.x)+pow2(a.y-b.y)+pow2(a.z-b.z));
}

inline void compute()
{
  Point mp = Point(50,50,50);
  double rate = 1;
  int max_pos;
  while(rate > EPS)
    {
      rep(_,100)
	{
	  max_pos = 0;
	  REP(j,1,V)
	    {
	      if(dist(mp,ps[max_pos]) < dist(mp,ps[j]))
		{
		  max_pos = j;
		}
	    }
	  mp.x += (ps[max_pos].x-mp.x) * rate;
	  mp.y += (ps[max_pos].y-mp.y) * rate;
	  mp.z += (ps[max_pos].z-mp.z) * rate;
	}
      rate = rate * 0.5;
    }
  printf("%.5lf\n",dist(mp,ps[max_pos]));
}

int main()
{
  while(scanf("%d",&V),V)
    {
      rep(i,V)
	{
	  scanf("%lf %lf %lf",&ps[i].x,&ps[i].y,&ps[i].z);
	}

      compute();

    }
  return 0;
}