Problem: An open-top box having a square bottom is placed on the floor. You see a number of needles vertically planted on its bottom.

You want to place a largest possible spheric balloon touching the box bottom, interfering with none of the side walls nor the needles.

Java Specific: Submitted Java programs may not use "java.awt.geom.Area". You may use it for your debugging purposes.

Figure H.1 shows an example of a box with needles and the corresponding largest spheric balloon. It corresponds to the first dataset of the sample input below.

<image>
Figure H.1. The upper shows an example layout and the lower shows the largest spheric balloon that can be placed.



Input

The input is a sequence of datasets. Each dataset is formatted as follows.


n w
x1 y1 h1
:
xn yn hn


The first line of a dataset contains two positive integers, n and w, separated by a space. n represents the number of needles, and w represents the height of the side walls.

The bottom of the box is a 100 × 100 square. The corners of the bottom face are placed at positions (0, 0, 0), (0, 100, 0), (100, 100, 0), and (100, 0, 0).

Each of the n lines following the first line contains three integers, xi, yi, and hi. (xi, yi, 0) and hi represent the base position and the height of the i-th needle. No two needles stand at the same position.

You can assume that 1 ≤ n ≤ 10, 10 ≤ w ≤ 200, 0 < xi < 100, 0 < yi < 100 and 1 ≤ hi ≤ 200. You can ignore the thicknesses of the needles and the walls.

The end of the input is indicated by a line of two zeros. The number of datasets does not exceed 1000.

Output

For each dataset, output a single line containing the maximum radius of a balloon that can touch the bottom of the box without interfering with the side walls or the needles. The output should not contain an error greater than 0.0001.

Example

Input

5 16
70 66 40
38 52 20
40 35 10
70 30 10
20 60 10
1 100
54 75 200
1 10
90 10 1
1 11
54 75 200
3 10
53 60 1
61 38 1
45 48 1
4 10
20 20 10
20 80 10
80 20 10
80 80 10
0 0


Output

26.00000
39.00000
130.00000
49.49777
85.00000
95.00000

Solution (in CPP):

Solution:
#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

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

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

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

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

	double x,y;
};

typedef Point Vector;

struct Line{
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

struct Circle{
	Point center;
	double height,r;
};

int N,H;
Circle info[10],work[10];

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

double arg(Vector p){
	return atan2(p.y,p.x);
}

Vector polar(double a,double r){
	return Point(cos(r)*a,sin(r)*a);
}

Point project(Line l,Point p){

	Vector base = l.p[1]-l.p[0];
	double r = dot(p-l.p[0],base)/norm(base);
	return l.p[0]+base*r;
}

//円と直線の交点を求める関数
vector<Point> getCrossPoints(Circle c,Line l){

	vector<Point> ret;

	Vector pr = project(l,c.center);
	Vector e = (l.p[1]-l.p[0])/abs(l.p[1]-l.p[0]);

	double base;

	if(fabs(c.r*c.r-norm(pr-c.center)) < EPS){

		base = 0;
	}else{
		base = sqrt(c.r*c.r-norm(pr-c.center));
	}

	ret.push_back(Point(pr+e*base));
	ret.push_back(Point(pr-e*base));

	return ret;
}

vector<Point> getCrossPoints(Circle c1,Circle c2){

	vector<Point> res;

	double d = abs(c1.center-c2.center);
	double a = acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
	double t = arg(c2.center-c1.center);

	res.push_back(Point(c1.center+polar(c1.r,t+a)));
	res.push_back(Point(c1.center+polar(c1.r,t-a)));

	return res;
}

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


bool is_OK(double R){

	for(int i = 0; i < N; i++){

		work[i] = info[i];
	}

	//球の中心を置けない範囲を円にする
	for(int i = 0; i < N; i++){

		if(info[i].height > R){

			work[i].r = R;

		}else{ //info[i].height <= R

			work[i].r = sqrt(info[i].height*(2*R-info[i].height));
		}
	}


	//正方形の壁の内側に、円を置き得る範囲の正方形を作る
	double L = 100,diff;
	double d_H = H;

	if(d_H > R){ //壁が球の半径より高い場合

		diff = R;

	}else{

		diff = sqrt(d_H*(2*R-d_H));
	}

	if(2*diff >= L){

		return false;
	}

	//4隅の点を作成
	Point left_under  = Point(diff,diff);
	Point right_under = Point(L-diff,diff);
	Point right_top = Point(L-diff,L-diff);
	Point left_top = Point(diff,L-diff);

	vector<Line> LINE;
	LINE.push_back(Line(left_top,left_under));
	LINE.push_back(Line(left_under,right_under));
	LINE.push_back(Line(right_under,right_top));
	LINE.push_back(Line(right_top,left_top));


	//★少なくとも1つ、どの円にも含まれていない(辺上を除く)地点があるか調べる
	vector<Point> POINT;

	POINT.push_back(left_under);
	POINT.push_back(right_under);
	POINT.push_back(right_top);
	POINT.push_back(left_top);

	vector<Point> tmp_point;

	for(int i = 0; i < N; i++){

		for(int k = 0; k < LINE.size(); k++){

			tmp_point =getCrossPoints(work[i],LINE[k]);

			for(int a = 0; a < tmp_point.size(); a++){

				POINT.push_back(tmp_point[a]);
			}
			tmp_point.clear();
		}

		//円と円の交点
		for(int k = i+1; k < N; k++){

			tmp_point = getCrossPoints(work[i],work[k]);

			for(int a = 0; a < tmp_point.size(); a++){

				POINT.push_back(tmp_point[a]);
			}

			tmp_point.clear();
		}
	}


	//少なくとも1つ、どの円の内部にも属していない点があれば良い
	for(int i = 0; i < POINT.size(); i++){

		bool FLG = true;

		for(int k = 0; k < N; k++){
			if(calc_dist(POINT[i],work[k].center)+EPS < work[k].r){
				FLG = false;
				break;
			}
		}
		if(!FLG)continue;

		if(POINT[i].x+EPS >= diff && POINT[i].x-EPS <= L-diff && //壁際との余裕も確認
				POINT[i].y+EPS >= diff && POINT[i].y-EPS <= L-diff){

			return true;
		}
	}

	return false;
}



void func(){

	for(int i = 0; i < N; i++){

		scanf("%lf %lf %lf",&info[i].center.x,&info[i].center.y,&info[i].height);
	}

	//半径について二分探索
	double L = 0,R = 1000,mid = (L+R)/2;
	double ans = 0;

	for(int loop = 0; loop < 100 && fabs(R-L) > EPS; loop++){

		if(is_OK(mid)){

			ans = mid;
			L = mid+EPS;

		}else{

			R = mid-EPS;
		}
		mid = (L+R)/2;
	}

	printf("%.10lf\n",ans);
}

int main(){

	while(true){

		scanf("%d %d",&N,&H);
		if(N == 0)break;

		func();
	}

	return 0;
}