Problem: Anchored Balloon

A balloon placed on the ground is connected to one or more anchors on the ground with ropes. Each rope is long enough to connect the balloon and the anchor. No two ropes cross each other. Figure E-1 shows such a situation.

<image>
Figure E-1: A balloon and ropes on the ground

Now the balloon takes off, and your task is to find how high the balloon can go up with keeping the rope connections. The positions of the anchors are fixed. The lengths of the ropes and the positions of the anchors are given. You may assume that these ropes have no weight and thus can be straightened up when pulled to whichever directions. Figure E-2 shows the highest position of the balloon for the situation shown in Figure E-1.

<image>
Figure E-2: The highest position of the balloon

Input

The input consists of multiple datasets, each in the following format.

> n
>  x1 y1 l1
>  ...
>  xn yn ln
>

The first line of a dataset contains an integer n (1 ≤ n ≤ 10) representing the number of the ropes. Each of the following n lines contains three integers, xi, yi, and li, separated by a single space. Pi = (xi, yi) represents the position of the anchor connecting the i-th rope, and li represents the length of the rope. You can assume that −100 ≤ xi ≤ 100, −100 ≤ yi ≤ 100, and 1 ≤ li ≤ 300. The balloon is initially placed at (0, 0) on the ground. You can ignore the size of the balloon and the anchors.

You can assume that Pi and Pj represent different positions if i ≠ j. You can also assume that the distance between Pi and (0, 0) is less than or equal to li−1. This means that the balloon can go up at least 1 unit high.

Figures E-1 and E-2 correspond to the first dataset of Sample Input below.

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

Output

For each dataset, output a single line containing the maximum height that the balloon can go up. The error of the value should be no greater than 0.00001. No extra characters should appear in the output.

Sample Input


3
10 10 20
10 -10 20
-10 10 120
1
10 10 16
2
10 10 20
10 -10 20
2
100 0 101
-90 0 91
2
0 0 53
30 40 102
3
10 10 20
10 -10 20
-10 -10 20
3
1 5 13
5 -3 13
-3 -3 13
3
98 97 168
-82 -80 193
-99 -96 211
4
90 -100 160
-80 -80 150
90 80 150
80 80 245
4
85 -90 290
-80 -80 220
-85 90 145
85 90 170
5
0 0 4
3 0 5
-3 0 5
0 3 5
0 -3 5
10
95 -93 260
-86 96 211
91 90 177
-81 -80 124
-91 91 144
97 94 165
-90 -86 194
89 85 167
-93 -80 222
92 -84 218
0


Output for the Sample Input


17.3205081
16.0000000
17.3205081
13.8011200
53.0000000
14.1421356
12.0000000
128.3928757
94.1879092
131.1240816
4.0000000
72.2251798






Example

Input

3
10 10 20
10 -10 20
-10 10 120
1
10 10 16
2
10 10 20
10 -10 20
2
100 0 101
-90 0 91
2
0 0 53
30 40 102
3
10 10 20
10 -10 20
-10 -10 20
3
1 5 13
5 -3 13
-3 -3 13
3
98 97 168
-82 -80 193
-99 -96 211
4
90 -100 160
-80 -80 150
90 80 150
80 80 245
4
85 -90 290
-80 -80 220
-85 90 145
85 90 170
5
0 0 4
3 0 5
-3 0 5
0 3 5
0 -3 5
10
95 -93 260
-86 96 211
91 90 177
-81 -80 124
-91 91 144
97 94 165
-90 -86 194
89 85 167
-93 -80 222
92 -84 218
0


Output

17.3205081
16.0000000
17.3205081
13.8011200
53.0000000
14.1421356
12.0000000
128.3928757
94.1879092
131.1240816
4.0000000
72.2251798

Solution (in CPP):

Solution:
#include<cstdio>
#include<complex>
#include<utility>
#include<vector>
#include<cmath>
#include<cassert>

using namespace std;

double eps=1e-9;

typedef complex<double> Point;
typedef complex<double> Vector;

template<class T> bool eq(T a,T b){
	return abs(a-b)<eps;
}

template<class T> int sgn(T r){
	return eq(r,0.0)?0:(r>0?1:-1);
}

struct Circle{
	Point center;
	double r;
	Circle(Point c,double r):center(c),r(r){}
	Circle(){}
};

struct Line{
	double a,b,c;//ax+by=c
	Line(){}
	Line(double a,double b,double c):a(a),b(b),c(c){}
	Line(Point p1,Point p2){//not verified
		if(eq(abs(p1-p2),0.0)){
			fprintf(stderr,"called Line for same points\n");
			assert(0);
		}
		double x1=p1.real(),y1=p1.imag();
		double x2=p2.real(),y2=p2.imag();
		a=y2-y1;
		b=-(x2-x1);
		c=x1*y2-x2*y1;
	}
};

void print(Point p){
	if(isnan(p.real())||isnan(p.imag())){
		printf("NaN Point\n");
		return;
	}
	printf("(%f,%f)\n",p.real(),p.imag());
}

double pointsDistance(Point p1,Point p2){/*abs(p1-p2)と書いてよい*/
	double dx=p1.real()-p2.real();
	double dy=p1.imag()-p2.imag();
	return sqrt(dx*dx+dy*dy);
}

double linePointDistance(Line l,Point p){
	double a=l.a,b=l.b,c=l.c;
	double x=p.real(),y=p.imag();
	double num=abs(a*x+b*y-c);
	double den=sqrt(a*a+b*b);
	return num/den;
}

Vector basisVector(Vector v){
	if(eq(v.real(),0.0)&&eq(v.imag(),0.0)) return v;
	return v/sqrt(norm(v));
}

Point linePointProjection(Line l,Point p){
	double dx=l.a,dy=l.b;
	double a=l.a,b=l.b,c=l.c;
	double x=p.real(),y=p.imag();
	Vector ba=basisVector(Vector(dx,dy));
	double num=a*x+b*y-c;
	double den=sqrt(a*a+b*b);
	Vector v=ba*(-num/den);
	return p+v;
}

vector<Point> circleLineIntersection(Circle c,Line l){
	vector<Point> res;
	Point p=linePointProjection(l,c.center);
	double d=linePointDistance(l,c.center);
	int s=sgn(d-c.r);
	if(s==1){
		return res;//empty
	}else if(s==0){
		res.push_back(p);
		return res;
	}else{
		double r=c.r;
		double t=sqrt(r*r-d*d);
		Vector e=basisVector(Vector(l.b,-l.a));
		res.push_back(p+t*e);
		res.push_back(p-t*e);
		return res;
	}
}

vector<Point> circlesIntersection(Circle c1,Circle c2){/*一致するとき処理できない*/
	if(eq(c1.center.real(),c2.center.real())&&eq(c1.center.imag(),c2.center.imag())&&
		eq(c1.r,c2.r)){
				Point p=Point(NAN,NAN);
				vector<Point> v;
				v.push_back(p);
				return v;
	}
	double d=pointsDistance(c1.center,c2.center);
	double r1=c1.r,r2=c2.r;
	double dif=max(r1,r2)-min(r1,r2);
	double sum=r1+r2;
	if(sgn(d-sum)==1||sgn(dif-d)==1){//d>sum||dif>d
		vector<Point> v;
		return v;
	}
	double x1=c1.center.real(),y1=c1.center.imag();
	double x2=c2.center.real(),y2=c2.center.imag();
	Line l=Line(-x1*2+x2*2,-y1*2+y2*2,r1*r1-r2*r2-(x1*x1-x2*x2)-(y1*y1-y2*y2));
	return circleLineIntersection(c1,l);
}

double det(double a,double b,double c,double d){
	return a*d-b*c;
}

Point linesIntersection(Line l1,Line l2){/*平行の時は常にNAN*/
	double a=l1.a,b=l1.b,c=l1.c;
	double d=l2.a,e=l2.b,f=l2.c;
	double den=det(a,b,d,e);
	double numx=det(c,b,f,e);
	double numy=det(a,c,d,f);
	if(eq(den,0.0)){
		return Point(NAN,NAN);
	}
	return Point(numx/den,numy/den);
}

//circlesIntersection verify AOJ1190 ICPC Domestic 2013 Balloon

double crossProduct(Vector a,Vector b){
	return (conj(a)*b).imag();
}

double dotProduct(Vector a,Vector b){
	return (conj(a)*b).real();
}

int ccw(Point p1,Point p2,Point p3){
	/*p1,p2,p3はすべて異なると仮定
	そうでない場合の戻り値は不定
	ではなく
	p1!=p2と仮定*/
	Vector b=p2-p1;
	Vector c=p3-p2;
	int s=sgn(crossProduct(b,c));
	if(s==1) return 1;//counterclockwise
	if(s==-1) return -1;//clockwise
	int t=sgn(dotProduct(b,c));
	if(t==-1) return 2;//3--1--2
	int u=sgn(norm(b)-norm(c));
	if(eq(norm(c),0.0)) return 0;//1==3
	if(u==-1) return -2;//1--2--3
	return 0;//1--3--2 or 2==3
}

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

int oneLineCCW(Point p1,Point p2,Point p3){
	/*p1!=p2かつp1,p2,p3は一直線上と仮定*/
	/*それ以外の時の戻り値は不定*/
	Vector b=p2-p1,c=p3-p1;
	if(sgn(dotProduct(b,c))==-1) return 2;//p3--p1--p2
	if(eq(abs(p1-p3),0.0)) return 1;//p1==p3--p2
	int s=sgn(norm(b)-norm(c));
	if(s==1) return 0;//p1--p3--p2
	if(s==0) return -1;//p1--p3==p2
	else return -2;//p1--p2--p3
}

double pointSegmentDistance(Point p,Segment s){
	Line l=s.l;
	double d=linePointDistance(l,p);
	Point pr=linePointProjection(l,p);
	int x=oneLineCCW(s.p1,s.p2,pr);
	if(x>=-1&&x<=1) return d;
	double a=abs(s.p1-p);
	double b=abs(s.p2-p);
	return min(a,b);
}

bool segmentsIntersect(Segment s1,Segment s2){
	Point p[2],q[2];
	p[0]=s1.p1,p[1]=s1.p2;
	q[0]=s2.p1,q[1]=s2.p2;
	return ccw(p[0],p[1],q[0])*ccw(p[0],p[1],q[1])<=0&&
		ccw(q[0],q[1],p[0])*ccw(q[0],q[1],p[1])<=0;
}

double segmentsDistance(Segment s1,Segment s2){
	bool flg=segmentsIntersect(s1,s2);
	if(flg) return 0;
	Point p[2],q[2];
	p[0]=s1.p1,p[1]=s1.p2;
	q[0]=s2.p1,q[1]=s2.p2;
	double res=-1;
	for(int k=0;k<2;k++){
		Point r=linePointProjection(s2.l,p[k]);
		if(abs(oneLineCCW(q[0],q[1],r))<=1){
			double tmp=abs(r-p[k]);
			if(res<0||tmp<res) res=tmp;
		}
		r=linePointProjection(s1.l,q[k]);
		if(abs(oneLineCCW(p[0],p[1],r))<=1){
			double tmp=abs(r-q[k]);
			if(res<0||tmp<res) res=tmp;
		}
	}
	for(int i=0;i<2;i++) for(int j=0;j<2;j++){
		double tmp=abs(p[i]-q[j]);
		if(res<0||tmp<res) res=tmp;
	}
	return res;
}

//segmentsDistance verified aoj cgl_2 d Distance

Point inputPoint(){
	double x,y;
	scanf("%lf%lf",&x,&y);
	return Point(x,y);
}

double x[11],y[11],l[11];

Circle circles[11];
vector<Point> cands;

bool inCircle(Circle c,Point p){//境界上でもtrue
	double d=pointsDistance(c.center,p);
	int s=sgn(d-c.r);
	if(s<=0) return true;
	return false;
}

int main(){
	while(true){
		int N;
		scanf("%d",&N);
		if(N==0) break;
		for(int i=0;i<N;i++) scanf("%lf%lf%lf",x+i,y+i,l+i);
		double lb=0;
		double ub=1000;
		for(int i=0;i<N;i++) ub=min(ub,l[i]);
		for(int stage=0;stage<100;stage++){
			double mid=(ub+lb)/2;
			for(int i=0;i<N;i++){
				circles[i]=Circle(Point(x[i],y[i]),sqrt(l[i]*l[i]-mid*mid));
			}
			cands.clear();
			for(int i=0;i<N;i++){
				for(int j=i+1;j<N;j++){
					vector<Point> tmp;
					tmp=circlesIntersection(circles[i],circles[j]);
					for(int k=0;k<tmp.size();k++){
						cands.push_back(tmp[k]);
					}
				}
			}
			//if(cands.size()==0){
				for(int i=0;i<N;i++){
					cands.push_back(circles[i].center);
				}
			//}
			bool ok=false;
			for(int i=0;i<cands.size();i++){
				bool flg=true;
				for(int j=0;j<N;j++){
					if(inCircle(circles[j],cands[i])==false) flg=false;
				}
				if(flg) ok=true;
			}
			if(ok) lb=mid;
			else ub=mid;
		}
		printf("%f\n",ub);
	}
	return 0;
}