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 <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <cstring>
#include <set>
#include <cassert>
#include <complex>

using namespace std;

typedef long long ll;

#define SIZE 400
#define LLINF 1000000000000000000LL

typedef complex<double> P;
const double eps = 1e-8;

double dot(P a, P b) {
  return (a * conj(b)).real();
}

double cross(P a, P b) {
  return (conj(a) * b).imag();
}

int ccw(P a, P b, P c) {
  if (cross(b-a, c-a) > eps) return 1;
  if (cross(b-a, c-a) < -eps) return -1;
  if (dot(b-a, c-a) < -eps) return -2;
  if (dot(a-b, c-b) < -eps) return 2;
  return 0;
}

double distanceLP(P a, P b, P c) {
  return abs(cross(b-a, c-a)) / abs(b-a);
}

bool isIntersectedCL(P c, double r, P a1, P a2) {
  return distanceLP(a1, a2, c) <= r + eps;
}

bool isIntersectedCC(P c1, double r1, P c2, double r2) {
  double dist = abs(c1 - c2);
  return abs(r1 - r2) <= dist + eps && dist - eps <= r1 + r2;
}

/* 円の円包含判定 (円1の内部に円2が存在するか) */
bool isContainedCC(P c1, double r1, P c2, double r2) {
  return abs(c1 - c2) + r2 < r1 - eps; //接する場合を含まない
  //return abs(c1 - c2) + r2 < r1 + P_eps; //接する場合を含まない
}

vector<P> getCrosspointCL(P c, double r, P a1, P a2) {
  if (!isIntersectedCL(c, r, a1, a2)) return {};

  P base1 = a2 - a1;
  P proj = a1 + base1 * dot(c - a1, base1) / norm(base1);
  P e = (a2 - a1) / abs(a2 - a1);
  P base2 = sqrt(r * r - norm(proj - c));
  return {proj - e*base2, proj + e*base2};
}

vector<P> getCrosspointCC(P c1, double r1, P c2, double r2) {
  if (!isIntersectedCC(c1, r1, c2, r2)) return {};

  double dist = abs(c1 - c2);
  double a = acos((r1 * r1 + dist*dist - r2 * r2) / (2 * r1 * dist));
  return { c1 + polar(r1, arg(c2 - c1) + a), c1 + polar(r1, arg(c2 - c1) - a) };
}

vector<P> getCrosspointLL(P a1, P a2, P b1, P b2) {
  P a = a2 - a1;
  P b = b2 - b1;
  return { a1 + a*cross(b, b1 - a1) / cross(b, a) };

}

bool solve() {
  int N, W;
  int x[10], y[10], h[10];

  scanf("%d%d", &N, &W);

  if (N == 0) return false;

  for (int i=0; i<N; i++) {
    scanf("%d%d%d", x+i, y+i, h+i);
  }

  double l = 0, r = -1;

  if (W < 50)
    r = (double)(50*50 + W*W) / (2 * W);
  else
    r = 50;

  P w1[4], w2[4];
  w1[0] = P(0, 0);   w2[0] = P(100, 0);
  w1[1] = P(0, 0);   w2[1] = P(0, 100);
  w1[2] = P(0, 100); w2[2] = P(100, 100);
  w1[3] = P(100, 0); w2[3] = P(100, 100);

  for(int _=0; _<100; _++) {
    double R = (l + r) / 2;

    P c[10];
    double rr[10], wdist;
    P a1[10], a2[10];

    //杭
    for (int i=0; i<N; i++) {
      if (h[i] < R) {
        // 点
        rr[i] = sqrt(R * R - (R - h[i]) * (R - h[i]));
        c[i] = P(x[i], y[i]);
      } else {
        //辺
        rr[i] = R;
        c[i] = P(x[i], y[i]);
      }
    }

    //壁
    if (W < R) {
      //辺
      double d = sqrt(R * R - (R - W) * (R - W));
      a1[0] = P(0, d);     a2[0] = P(100, d);
      a1[1] = P(d, 0);     a2[1] = P(d, 100);
      a1[2] = P(0, 100-d); a2[2] = P(100, 100-d);
      a1[3] = P(100-d, 0); a2[3] = P(100-d, 100);
      wdist = d;
    } else {
      //面
      a1[0] = P(0, R);     a2[0] = P(100, R);
      a1[1] = P(R, 0);     a2[1] = P(R, 100);
      a1[2] = P(0, 100-R); a2[2] = P(100, 100-R);
      a1[3] = P(100-R, 0); a2[3] = P(100-R, 100);
      wdist = R;
    }

    bool f = false;

    for (int i=0; i<N+4; i++) {
      bool ok = true;
      for (int j=0; j<N+4; j++) {
        if (i == j) continue;

        int a = i, b = j;
        if (a > b) swap(a, b);

        vector<P> cps;

        if (a < N && b < N) {
          //円と円
          if (isContainedCC(c[a], rr[a], c[b], rr[b]) || isContainedCC(c[b], rr[b], c[a], rr[a])) {
            ok = false;
            continue;
          }

          cps = getCrosspointCC(c[a], rr[a], c[b], rr[b]);
        } else if (a < N) {
          //円と直線
          if (distanceLP(w1[b-N], w2[b-N], c[a]) + rr[a] < wdist - eps) {
            ok = false;
            continue;
          }

          cps = getCrosspointCL(c[a], rr[a], a1[b-N], a2[b-N]);
        } else {
          //直線と直線
          if (abs(a - b) % 2 == 0) continue;
          cps = getCrosspointLL(a1[a-N], a2[a-N], a1[b-N], a2[b-N]);
        }


        ok &= cps.size() == 0;

        bool okcp = true;

        for (P cp : cps) {
          if (-eps > cp.real() || cp.real() > 100 + eps || -eps > cp.imag() || cp.imag() > 100 + eps) continue;

          okcp = true;
          // 杭
          for (int i=0; i<N; i++) {
            double d = abs(c[i] - cp);
            if (d >= R - eps) continue;

            if (h[i] < R) {
              //点
              okcp &= R - sqrt(R * R - d * d) > h[i] - eps;
            } else {
              //面
              okcp = false;
            }
          }

          //壁
          for (int i=0; i<4; i++) {
            double d = distanceLP(w1[i], w2[i], cp);
            if (d >= R - eps) continue;

            if (W < R) {
              okcp &= R - sqrt(R*R - d*d) > W - eps;
            } else {
              okcp = false;
            }
          }

          if (okcp) { f = true; break; }
        }
      }

      if (ok) f = true;
    }

    if (f) {
      l = R;
    } else {
      r = R;
    }
  }

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

  return true;
}

int main() {
  while(solve());
}