Problem: During a voyage of the starship Hakodate-maru (see Problem A), researchers found strange synchronized movements of stars. Having heard these observations, Dr. Extreme proposed a theory of "super stars". Do not take this term as a description of actors or singers. It is a revolutionary theory in astronomy.

According to this theory, stars we are observing are not independent objects, but only small portions of larger objects called super stars. A super star is filled with invisible (or transparent) material, and only a number of points inside or on its surface shine. These points are observed as stars by us.

In order to verify this theory, Dr. Extreme wants to build motion equations of super stars and to compare the solutions of these equations with observed movements of stars. As the first step, he assumes that a super star is sphere-shaped, and has the smallest possible radius such that the sphere contains all given stars in or on it. This assumption makes it possible to estimate the volume of a super star, and thus its mass (the density of the invisible material is known).

You are asked to help Dr. Extreme by writing a program which, given the locations of a number of stars, finds the smallest sphere containing all of them in or on it. In this computation, you should ignore the sizes of stars. In other words, a star should be regarded as a point. You may assume the universe is a Euclidean space.



Input

The input consists of multiple data sets. Each data set is given in the following format.


n
x1 y1 z1
x2 y2 z2
...
xn yn zn


The first line of a data set contains an integer n, which is the number of points. It satisfies the condition 4 ≤ n ≤ 30.

The locations of n points are given by three-dimensional orthogonal coordinates: (xi, yi, zi) (i = 1,..., n). Three coordinates of a point appear in a line, separated by a space character.

Each value is given by a decimal fraction, and is between 0.0 and 100.0 (both ends inclusive). Points are at least 0.01 distant from each other.

The end of the input is indicated by a line containing a zero.

Output

For each data set, the radius ofthe smallest sphere containing all given points should be printed, each in a separate line. The printed values should have 5 digits after the decimal point. They may not have an error greater than 0.00001.

Example

Input

4
10.00000 10.00000 10.00000
20.00000 10.00000 10.00000
20.00000 20.00000 10.00000
10.00000 20.00000 10.00000
4
10.00000 10.00000 10.00000
10.00000 50.00000 50.00000
50.00000 10.00000 50.00000
50.00000 50.00000 10.00000
0


Output

7.07107
34.64102

Solution (in CPP):

Solution:
#include "bits/stdc++.h"
using namespace std;
#ifdef _DEBUG
#include "dump.hpp"
#else
#define dump(...)
#endif

//#define int long long
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define all(c) begin(c),end(c)
const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
const int MOD = (int)(1e9) + 7;
template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }

//#define double long double
const double EPS = 1e-8; //???????????¨????????´
#define equals(a,b) (fabs((a)-(b)) < EPS)
template<class T> bool chequals(T &a, const T &b) { if (fabs(a - b) < EPS) { a = b; return true; } return false; }

struct Point {
	double x, y, z;
	Point() :x(0.0), y(0.0), z(0.0) {}
	Point(double x, double y, double z) :x(x), y(y), z(z) {}

	Point &operator+=(const Point &p) { x += p.x; y += p.y; z += p.z; return *this; }
	Point &operator-=(const Point &p) { x -= p.x; y -= p.y; z -= p.z; return *this; }
	Point &operator*=(double a) { x *= a; y *= a; z *= a; return *this; }
	Point &operator/=(double a) { x /= a; y /= a; z /= a; return *this; }

	bool operator<(const Point &p)const {
		if (x < p.x)return true;
		if (x > p.x)return false;
		if (y < p.y)return true;
		if (y > p.y)return false;
		if (z < p.z)return true;
		return false;
	}
	bool operator==(const Point &p)const { return equals(x, p.x) && equals(y, p.y) && equals(z, p.z); }

	double abs() { return sqrt(norm()); }
	double norm() { return x*x + y*y + z*z; }

};
Point operator+(const Point &p1, const Point &p2) { return Point(p1) += p2; }
Point operator-(const Point &p1, const Point &p2) { return Point(p1) -= p2; }
Point operator*(const Point &p, double a) { return Point(p) *= a; }
Point operator/(const Point &p, double a) { return Point(p) /= a; }
inline ostream &operator << (ostream &os, const Point &p) { os << p.x << " " << p.y << " " << p.z; return os; }
inline istream &operator >> (istream &is, Point &p) { double x, y, z; is >> x >> y >> z; p = Point(x, y, z); return is; }

struct Vector :public Point {
	using Point::Point;
	Vector() {}
	Vector(const Point &P) { x = P.x; y = P.y; z = P.z; }
	Vector unit() { return *this / abs(); }
};

//http://www.math.s.chiba-u.ac.jp/~yasuda/Chiba/Lec/naiseki.pdf
//?????? dot product
double dot(Vector a, Vector b) {
	double ret = a.x*b.x + a.y*b.y + a.z*b.z;
	chequals(ret, 0.0);
	return ret;
}
//?????? cross product
Vector cross(Vector a, Vector b) {
	Vector ret;
	ret.x = a.y*b.z - a.z*b.y; chequals(ret.x, 0.0);
	ret.y = a.z*b.x - a.x*b.z; chequals(ret.y, 0.0);
	ret.z = a.x*b.y - a.y*b.x; chequals(ret.z, 0.0);
	return ret;
}

struct Line {
	Point p1, p2;
	Line() {}
	Line(Point p1, Point p2) :p1(p1), p2(p2) {}
};

struct Segment :public Line {
	using Line::Line;
	Segment() {}
	Segment(const Line &L) { p1 = L.p1; p2 = L.p2; }
	Vector vec() { return p2 - p1; }
};

//???
struct Sphere {
	Point c;
	double r;
	Sphere() {}
	Sphere(const Point &c, double r) :c(c), r(r) {};
};

using Polygon = vector<Point>;

//?????¢
struct Plane {
	double a, b, c, d;//ax+by+cz+d=0
	Plane() {}
	Plane(double a, double b, double c, double d) :a(a), b(b), c(c), d(d) {}
	Plane(const Vector &n, const Point &p) :a(n.x), b(n.y), c(n.z) {
		d = -(a*p.x + b*p.y + c*p.z);
	};

	Vector normal() { return Vector(a, b, c); } //??????
	Point point() { return Point(a*d, b*d, c*d); }
};

struct Triangle {
	Point p1, p2, p3;
	Triangle() {}
	Triangle(const Point &p1, const Point &p2, const Point &p3) :p1(p1), p2(p2), p3(p3) {}
	Plane plane() {
		Vector OA(p2 - p1), OB(p3 - p1);
		Vector n(cross(OA, OB));
		return Plane(n, p1);
	}
};

//?????????????????¢??? degree to radian
double rad(double deg) { return acos(-1)*deg / 180; }
//????§? argument
double arg(Vector p) { return atan2(p.y, p.x); }
//2??????????????????????§????
double angle(Vector a, Vector b) {
	double lena = a.abs(), lenb = b.abs();
	if (lena == 0 || lenb == 0)return 0; //?§£??????
	double costheta = dot(a, b) / (lena*lenb);
	if (equals(costheta, 1))costheta = 1; //????????????
	return acos(costheta);
}

//??´?????????
bool is_orthogonal(Vector a, Vector b) { return equals(dot(a, b), 0.0); }
bool is_orthogonal(Segment s1, Segment s2) { return equals(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0); }

//?°???±
Point project(Segment s, Point p) {
	Vector base = s.p2 - s.p1;
	double r = dot(p - s.p1, base) / base.norm();
	return s.p1 + base*r;
}
//????°?
Point reflect(Segment s, Point p) { return p + (project(s, p) - p)*2.0; }

//2??????????????¢
double get_distance(Point a, Point b) { return (a - b).abs(); }
//http://www.sousakuba.com/Programming/gs_dot_line_distance.html
//??´?????¨???????????¢
double get_distance(Line l, Point p) { return cross(l.p2 - l.p1, p - l.p1).abs() / (l.p2 - l.p1).abs(); }
//????????¨???????????¢
double get_distance(Segment s, Point p) {
	if (dot(s.p2 - s.p1, p - s.p1) < 0.0)return get_distance(p, s.p1);
	if (dot(s.p1 - s.p2, p - s.p2) < 0.0)return get_distance(p, s.p2);
	return get_distance(Line(s), p);
}

//?????¨?????????????????????
bool intersect(Sphere SP, Segment S) {
	return SP.r + EPS >= get_distance(S, SP.c);
}

//?????¨??´????????????
pair<Point, Point> get_cross_points(Sphere SP, Line L) {
	assert(intersect(SP, L));
	Vector pr = project(L, SP.c);
	Vector e = (L.p2 - L.p1) / (L.p2 - L.p1).abs();
	double base = sqrt(SP.r*SP.r - (pr - SP.c).norm());
	return make_pair(pr + e*base, pr - e*base);
}


//????§???¢?????????
Point center(const Polygon &P) {
	Point ret;
	for (auto &p : P)ret += p;
	ret /= P.size();
	return ret;
}


// ????°?????????? ?±±?????????
// 2?¬? https://en.wikipedia.org/wiki/Smallest-circle_problem
// k?¬? https://en.wikipedia.org/wiki/Bounding_sphere
// O(N)???O(N^4)?§£????????????
void boundingSphere() {
	cout << fixed << setprecision(10);
	for (int N; cin >> N&&N;) {
		Polygon p(N);
		// ????????????
		vector<double> v(N, 1.0);
		rep(i, 0, N)
			cin >> p[i]/* >> v[i]*/;

		Point g = center(p);
		vector<double> cost(N);
		// ????????????????????????????????´
		double move = 0.5, y = 0.99;
		while (move > EPS) {
			rep(i, 0, N)
				cost[i] = get_distance(g, p[i]) / v[i];
			int maxidx = max_element(all(cost)) - cost.begin();
			g += (p[maxidx] - g) *move;
			move *= y;
		}

		double ans = 0;
		rep(i, 0, N)
			chmax(ans, get_distance(g, p[i]) / v[i]);
		// ????°??????????
		cout << ans << endl;
	}
}

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	boundingSphere();
	return 0;
}