#include<cassert>
#include<cstdio>
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)

const double eps = 1e-10;

class Point{
public:
  double x,y,z;
  double dist(){
    return sqrt(x*x+y*y+z*z);
  }
  Point operator+(Point a)const{
    return (Point){x+a.x,y+a.y,z+a.z};
  }
  Point operator-(Point a)const{
    return (Point){x-a.x,y-a.y,z-a.z};
  }
  Point operator*(double a)const{
    return (Point){a*x,a*y,a*z};
  }
  Point operator/(double a)const{
    return (Point){x/a,y/a,z/a};
  };
};

//Lib
double dot(Point A,Point B){
  return A.x*B.x + A.y*B.y + A.z*B.z;
}

//Lib
Point CircumCenter(Point A,Point B,Point C){
  Point ret;
  double a=(B-C).dist(),b=(C-A).dist(),c=(A-B).dist();
  double cosA=dot(B-A,C-A)/(b*c);
  double s=(c-b*cosA)/(2*c*(1-cosA*cosA));
  double t=(b-c*cosA)/(2*b*(1-cosA*cosA));
  ret=(B-A)*s+(C-A)*t+A;
  return ret;
}

//Lib
Point normal_vector(Point a,Point b){
  Point ret =(Point){a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x};
  double len=ret.dist();
  ret=ret/len;
  return ret;
}

double isp(Point a,Point b,Point c){
  return (a-c).dist()+(b-c).dist() < (a-b).dist() + eps;
}

bool is_contain_all(Point a,double r,vector<Point> &in){
  rep(i,in.size()){
    if ((in[i]-a).dist() <r+eps);
    else return false;
  }
  return true;
}

double solve(Point cir,Point norm,vector<Point> &in,Point check,
	     double d,double f){//d=(A+B)/2).dist(),f=(cir-(A+B)/2)/dist()
  double l = 0,r=50;
  double mid,ret=1e6;
  //  while(r-l >eps){
  rep(i,100){
    double mid = (l+r)/2;
    Point vec = cir+norm*mid;
    double radius = (vec-check).dist();

    if (is_contain_all(vec,radius,in))r=mid-eps,ret=min(ret,radius);
    else l=mid+eps;
  }
  return ret;
}

double solve(vector<Point> & in){
  double ret = 1e6;
  
  rep(i,in.size()){
    REP(j,i+1,in.size()){
      REP(k,j+1,in.size()){
	if (isp(in[i],in[j],in[k])||isp(in[i],in[k],in[j])
	    ||isp(in[j],in[k],in[i])){
	  continue;
	}
	Point cir = CircumCenter(in[i],in[j],in[k]);
	double r =(cir-in[i]).dist();

	if (is_contain_all(cir,r,in))ret=min(ret,r);
	
	Point norm= normal_vector(in[j]-in[i],in[k]-in[i]);
	Point tmp = (in[i]+in[j])/2-in[i];
	Point tmp2= (cir-(in[i]+in[j])/2);
	ret=min(ret,solve(cir,norm,in,in[i],tmp.dist(),tmp2.dist()));
	norm=norm*-1;
	ret=min(ret,solve(cir,norm,in,in[i],tmp.dist(),tmp2.dist()));
	
      }
    }
  }
  
  rep(i,in.size()){
    REP(j,i+1,in.size()){
      Point center=(in[i]+in[j])/2;
      double r = (center-in[i]).dist();
      if (is_contain_all(center,r,in))ret=min(ret,r);
    }
  }

  return ret;
}

int main(){
  int n;
  while(cin>>n && n){
    vector<Point> in;
    rep(i,n){
      double x,y,z;
      cin>>x>>y>>z;
      in.push_back((Point){x,y,z});
    }

    printf("%.8lf\n",solve(in));
  }
}