// http://poj.org/problem?id=3528
// http://acm.hdu.edu.cn/showproblem.php?pid=3662
// http://blog.csdn.net/jasonzhu8/article/details/6159950

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

const double EPS = 1e-6;

inline bool eq(const double x, const double y) {
	return x + EPS > y && y + EPS > x;
}

inline bool zero(const double x) {
	return x < EPS && x > -EPS;
}

struct Point {
	double x, y, z;

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

	Point operator+(const Point& p) const {
		return Point(x + p.x, y + p.y, z + p.z);
	}

	Point operator-(const Point& p) const {
		return Point(x - p.x, y - p.y, z - p.z);
	}

	Point operator*(const double k) const {
		return Point(x * k, y * k, z * k);
	}

	Point operator*(const Point& p) const {
		return Point(y * p.z - z * p.y, z * p.x - x * p.z, x * p.y - y * p.x);
	}

	double operator^(const Point& p) const {
		return x * p.x + y * p.y + z * p.z;
	}

	double len() const {
		return sqrt(x * x + y * y + z * z);
	}

	Point trunc(const double k) const {
		double t = k / len();
		return Point(x * t, y * t, z * t);
	}

	bool operator==(const Point& p) const {
		return eq(x, p.x) && eq(y, p.y) && eq(z, p.z);
	}
};

// signed volumn of tetrahedron
// positive iff a, b, c are in counterclockwise when seeing from d
double volumn4(const Point& a, const Point& b, const Point& c, const Point& d) {
	return (b - a) * (c - a) ^ (d - a);
}

struct ConvexHall3D {
	struct Face {
		int v[3];

		Face(int a, int b, int c) {
			v[0] = a;
			v[1] = b;
			v[2] = c;
		}

		const int& operator[](const int i) const {
			return v[i];
		}

		int& operator[](const int i) {
			return v[i];
		}
	};

	Point normal(const Face& f) const {
		return (p[f[1]] - p[f[0]]) * (p[f[2]] - p[f[0]]);
	}

	static const int MAXN = 128;

	int n; // number of vertices
	int t; // temp
	Point p[MAXN]; // vertices
	vector<Face> f;
	int type[MAXN][MAXN];

	bool build(int _n, Point _p[]) {
		// initialize
		n = _n;
		for (int i = 0; i < n; ++i) {
			p[i] = _p[i];
		}
		f.clear();

		// if n < 3, there is no face
		if (n < 4) {
			return false;
		}

		// find two different points
		for (t = 1; t < n && p[t] == p[0]; ++t);
		if (t == n) {
			return false;
		}
		swap(p[t], p[1]);
		
		// find the third point not in the same line
		for (t = 2; t < n && zero(((p[t] - p[0]) * (p[t] - p[1])).len()); ++t);
		if (t == n) {
			return false;
		}
		swap(p[t], p[2]);

		// find the forth point not in the same plane
		for (t = 3; t < n && zero(volumn4(p[0], p[1], p[2], p[t])); ++t);
		if (t == n) {
			return false;
		}
		swap(p[t], p[3]);
		

		//for (int i = 0; i < n; ++i) { printf("p[%d]: (%.0f, %.0f, %.0f)\n", i, p[i].x, p[i].y, p[i].z); } puts("");

		// p[fac[0]],p[fac[1]],p[fac[2]],Ptwo faces
		f.push_back(Face(0, 1, 2));
		f.push_back(Face(2, 1, 0));
		memset(type, 0, sizeof(type));
		for (int i = 3; i < n; ++i) {
			vector<Face> nf;
			for (int j = 0; j < (int)f.size(); ++j) {
				const Face& fa = f[j];
				// outside ? 1 : -1
				t = volumn4(p[fa[0]], p[fa[1]], p[fa[2]], p[i]) < EPS ? -1 : 1;
				if (t == -1) {
					nf.push_back(fa);
				}
				// for each edge
		 		for (int k = 0; k < 3; ++k) {
					// an edge from v1 to v2
					int v1 = fa[k], v2 = fa[(k + 1) % 3];
		 			if (type[v1][v2] == 0) {
						type[v2][v1] = t;
					} else{
						if (type[v1][v2] != t) {
							if (t == 1) {
								nf.push_back(Face(v1, v2, i));
							} else {
								nf.push_back(Face(v2, v1, i));
							}
						}
						type[v1][v2] = 0;
					}
				}
			}
			f.swap(nf);
		//	for (int j = 0; j < (int)f.size(); ++j) { printf("f[%d] = %d %d %d\n", j, f[j][0], f[j][1], f[j][2]); } puts("");
		}
		return (int)f.size();
	}
/*	int countFaces() const {
		vector<bool> mark(f.size(), true);
		int ret = 0;
		for (int i = 0; i < (int)f.size(); ++i) {
			if (mark[i]) {
				++ret;
		 		for (int j = i + 1; j < (int)f.size(); ++j) {
					if (mark[j] && zero(volumn4(p[f[i][0]], p[f[i][1]], p[f[i][2]], p[f[j][0]])) && normal(f[i]).trunc(1.0) == normal(f[j]).trunc(1.0)) {
			mark[j] = false;
					}
				}
			}
		}
		return ret;
	}

	double surfaceArea() const {
		double ret = 0.0;
		for (int i = 0; i < (int)f.size(); ++i) {
			const Point& p0 = p[f[i][0]];
			const Point& p1 = p[f[i][1]];
			const Point& p2 = p[f[i][2]];
			ret += ((p1 - p0) * (p2 - p0)).len();
		} 
		return ret * 0.5;
	}

	double volumn() const {
		double ret = 0.0;
		Point o(0.0, 0.0, 0.0);
		for (int i = 0; i < (int)f.size(); ++i) {
			const Point& p0 = p[f[i][0]];
			const Poi		nt& p1 = p[f[i][1]];
			const Point& p2 = p[f[i][2]];
			ret += volumn4(p0, p1, p2, o);
		}
		return ret;
	}*/
	double calc(){
		Point P = p[0],tp;
		double tv=0;
		for(int i=0;i<f.size();++i){
			const Face &fac = f[i];
			double tmp = volumn4(p[fac[0]],p[fac[1]],p[fac[2]],P);
			tp =tp +( ((p[fac[0]]+p[fac[1]])+(p[fac[2]]+P)) * tmp);
			tv += tmp;
		}
		P = tp * (0.25/tv);
		double ans = 9e9;
		for(int i=0;i<f.size();++i){
			const Face & fac = f[i];
			double tmp  =fabs(volumn4(p[fac[0]],p[fac[1]],p[fac[2]],P) /
				((p[fac[1]]-p[fac[0]])*(p[fac[2]]-p[fac[0]])).len());
			if(tmp <ans) ans = tmp;
		}
		return ans;
	}
} ch3d;

int n;
Point p[120];

int main() {
	while (scanf("%d", &n) != EOF) {
		double tx=0,ty=0,tz=0;
		for (int i = 0; i < n; ++i) 
			scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z);
		int k = 0;
		for(int i=0;i<n;++i){
			bool ok = true;
			for(int j=0;j<k;++j)
				if((p[i]-p[j]).len()<EPS)ok = false;
			if(ok)p[k++]=p[i];
		}
		n = k;
		ch3d.build(n, p);
		printf("%.3lf\n",ch3d.calc());
	}
	return 0;
}
