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>

using namespace std;

const double EPS = 1e-10, PI = acos(-1);

inline bool eq(double a, double b) { return abs(b - a) < EPS; }

#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
#define prev(P, i) P[(i+P.size()-1) % P.size()]
enum
{
  OUT, ON, IN
};
namespace Geometory
{
  struct Point
  {
    double x, y;

    Point() {};

    Point(double x, double y) : x(x), y(y) {};

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

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

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

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

    Point operator/(const double b) const { return Point(x / b, y / b); }

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

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

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

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

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

    Point rotate(double theta) { return Point(cos(theta) * x - sin(theta) * y, sin(theta) * x + cos(theta) * y); }

    Point rotate90() { return Point(-y, x); }

    friend ostream &operator<<(ostream &os, Point &p) { return os << "(" << p.x << "," << p.y << ")"; }

    friend istream &operator>>(istream &is, Point &a) { return is >> a.x >> a.y; }
  };

  struct Line
  {
    Point a, b;

    Line() {};

    Line(Point a, Point b) : a(a), b(b) {};

    friend ostream &operator<<(ostream &os, Line &p) { return os << "(" << p.a.x << "," << p.a.y << ") to (" << p.b.x << "," << p.b.y << ")"; }

    friend istream &operator>>(istream &is, Line &a) { return is >> a.a.x >> a.a.y >> a.b.x >> a.b.y; }
  };

  struct Segment
  {
    Point a, b;

    Segment() {};

    Segment(Point a, Point b) : a(a), b(b) {};

    friend ostream &operator<<(ostream &os, Segment &p) { return os << "(" << p.a.x << "," << p.a.y << ") to (" << p.b.x << "," << p.b.y << ")"; }

    friend istream &operator>>(istream &is, Segment &a) { return is >> a.a.x >> a.a.y >> a.b.x >> a.b.y; }
  };

  struct Circle
  {
    Point p;
    double r;

    Circle() {};

    Circle(Point p, double r) : p(p), r(r) {};
  };

  typedef vector< Point > Polygon;
  typedef vector< Segment > Segments;
  typedef vector< Line > Lines;
  typedef vector< Circle > Circles;
  typedef pair< Point, Point > PointPoint;

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

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

  int ccw(const Point &a, Point b, Point c)
  {
    b = b - a, c = c - a;
    if(cross(b, c) > EPS) return +1;  // a ??? b ?????§ ??????????¨??????????????????? c
    if(cross(b, c) < -EPS) return -1; // a ??? b ?????§ ???????¨??????????????????? c
    if(dot(b, c) < 0) return +2;  // c -- a -- b?????§????????´??????
    if(b.norm() < c.norm()) return -2; // a -- b -- c?????§????????´??????
    return 0;  // a -- c -- b?????§????????´??????
  }

  Point Projection(const Line &l, const Point &p)
  {
    double t = dot(p - l.a, l.a - l.b) / (l.a - l.b).norm();
    return l.a + (l.a - l.b) * t;
  }

  Point Projection(const Segment &l, const Point &p)
  {
    double t = dot(p - l.a, l.a - l.b) / (l.a - l.b).norm();
    return l.a + (l.a - l.b) * t;
  }

  Point Reflection(const Line &l, const Point &p)
  {
    return p + (Projection(l, p) - p) * 2.0;
  }

  double Distance(const Line &l, const Point &p)
  { //OK
    return (p - Projection(l, p)).abs();
  }

  bool Intersect(const Line &l, const Line &m)
  {
    return abs(cross(l.b - l.a, m.b - m.a)) > EPS || abs(cross(l.b - l.a, m.b - l.a)) < EPS;
  }

  bool Intersect(const Line &l, const Segment &s)
  {
    return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
  }

  bool Intersect(const Line &l, const Point &p)
  {
    return abs(ccw(l.a, l.b, p)) != -1;
  }

  bool Intersect(const Segment &s, const Segment &t)
  {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
  }

  bool Intersect(const Segment &s, const Point &p)
  {
    return ccw(s.a, s.b, p) == 0;
  }

  bool Intersect(const Circle &c, const Line &l)
  {
    return Distance(l, c.p) <= c.r + EPS;
  }

  bool Intersect(const Circle &c, const Point &p)
  {
    return abs((p - c.p).abs() - c.r) < EPS;
  }

  int Intersect(const Circle &c, const Segment &l)
  {
    if((Projection(l, c.p) - c.p).norm() - c.r * c.r > EPS) return 0;
    const double d1 = (c.p - l.a).abs(), d2 = (c.p - l.b).abs();
    if(d1 < c.r + EPS && d2 < c.r + EPS) return 0;
    if(d1 < c.r - EPS && d2 > c.r + EPS || d1 > c.r + EPS && d2 < c.r - EPS) return 1;
    const Point h = Projection(l, c.p);
    if(dot(l.a - h, l.b - h) < 0) return 2;
    return 0;
  }

  bool Intersect(const Circle &a, const Circle &b)
  {
    return ((a.p - b.p).norm() - (a.r + b.r) * (a.r + b.r) < EPS) &&
           ((a.p - b.p).norm() - (a.r - b.r) * (a.r - b.r) > -EPS);
  }

  double Distance(const Segment &s, const Point &p)
  {
    Point r = Projection(s, p);
    if(Intersect(s, r)) return (r - p).abs();
    return min((s.a - p).abs(), (s.b - p).abs());
  }

  double Distance(const Segment &a, const Segment &b)
  {
    if(Intersect(a, b)) return 0;
    return min(min(Distance(a, b.a), Distance(a, b.b)), min(Distance(b, a.a), Distance(b, a.b)));
  }

  double Distance(const Line &l, const Line &m)
  {
    return Intersect(l, m) ? 0 : Distance(l, m.a);
  }

  double Distance(const Line &l, const Segment &s)
  { //OK
    if(Intersect(l, s)) return 0;
    return min(Distance(l, s.a), Distance(l, s.b));
  }

  double Distance(const Point &a, const Point &b)
  { //OK
    return (a - b).abs();
  }

  Point Crosspoint(const Segment &l, const Segment &m)
  { //OK
    double A = cross(l.b - l.a, m.b - m.a);
    double B = cross(l.b - l.a, l.b - m.a);
    if(abs(A) < EPS && abs(B) < EPS) return m.a; // same line
    return m.a + (m.b - m.a) * B / A;
  }

  PointPoint Crosspoint(const Circle &c, const Line l)
  {
    Point hp = Projection(l, c.p), h = hp - c.p;
    const double d2 = h.norm();
    Point v = (l.b - l.a) * sqrt(c.r * c.r - d2) / (l.b - l.a).abs();
    return PointPoint(hp - v, hp + v);
  }

  PointPoint Crosspoint(const Circle &c, const Segment &l)
  {
    Line aa = Line(l.a, l.b);
    if(Intersect(c, l) == 2) return Crosspoint(c, aa);
    PointPoint ret = Crosspoint(c, aa);
    if(dot(l.a - ret.first, l.b - ret.first) < 0) ret.second = ret.first;
    else ret.first = ret.second;
    return ret;
  }

  PointPoint Crosspoint(const Circle &c1, const Circle &c2)
  { //OK
    double d = (c1.p - c2.p).abs();
    double s = (c1.r + c2.r + d) / 2;
    double S = sqrt(s * (s - c1.r) * (s - c2.r) * (s - d));
    double h = 2 * S / d;
    Point v = (c2.p - c1.p) / (c2.p - c1.p).abs();
    double m = sqrt(c1.r * c1.r - h * h);
    return PointPoint(c1.p + v * m + Point(0, 1) * h * v, c1.p + v * m - Point(0, 1) * h * v);
  }

  bool parallel(const Line &a, const Line &b)
  {
    return abs(cross(a.b - a.a, b.b - b.a)) < EPS;
  }

  bool orthogonal(const Line &a, const Line &b)
  {
    return abs(dot(a.a - a.b, b.a - b.b)) < EPS;
  }

  int Contains(const Polygon &Q, const Point &p)
  {
    bool in = false;
    for(int i = 0; i < Q.size(); i++) {
      Point a = curr(Q, i) - p, b = next(Q, i) - p;
      if(a.y > b.y) swap(a, b);
      if(a.y <= 0 && 0 < b.y && cross(a, b) < 0) in = !in;
      if(cross(a, b) == 0 && dot(a, b) <= 0) return ON;
    }
    return in ? IN : OUT;
  }

  bool Contains(const Circle &c, const Point &p)
  {
    return (c.p - p).abs() < c.r + EPS;
  }

  double Area2(const Polygon &p)
  { //OK
    double A = 0;
    for(int i = 0; i < p.size(); ++i) {
      A += cross(curr(p, i), next(p, i));
    }
    return A;
  }

  bool IsConvex(const Polygon &p)
  {
    for(int i = 0; i < p.size(); i++) {
      if(ccw(prev(p, i), curr(p, i), next(p, i)) == -1) return false;
    }
    return true;
  }

  Polygon Convex_Hull(Polygon &p)
  {
    int n = p.size(), k = 0;
    if(n >= 3) {
      sort(p.begin(), p.end());
      vector< Point > ch(2 * n);
      for(int i = 0; i < n; ch[k++] = p[i++]) {
        while(k >= 2 && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
      }
      for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) {
        while(k >= t && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
      }
      ch.resize(k - 1);
      return ch;
    } else {
      return p;
    }
  }

  double Convex_Diameter(Polygon &p)
  {
    int n = p.size();
    int is = 0, js = 0;
    for(int i = 1; i < n; i++) {
      if(p[i].y > p[is].y) is = i;
      if(p[i].y < p[js].y) js = i;
    }
    double maxdis = (p[is] - p[js]).norm();

    int maxi, maxj, i, j;
    i = maxi = is;
    j = maxj = js;
    do {
      if(cross(next(p, i) - curr(p, i), next(p, j) - curr(p, j)) >= 0) {
        j = (j + 1) % n;
      } else {
        i = (i + 1) % n;
      }
      if((p[i] - p[j]).norm() > maxdis) {
        maxdis = (p[i] - p[j]).norm();
        maxi = i;
        maxj = j;
      }
    } while(i != is || j != js);
    return maxdis;
  }
};

using namespace Geometory;

int N, W;
int X[10], Y[10], H[10];

bool check(double r)
{
  auto getPadding = [&](double height)
  {
    if(r > height) return (r - sqrt(r * r - (r - height) * (r - height)));
    return (0.0);
  };

  vector< Circle > circles(N);
  for(int i = 0; i < N; i++) {
    circles[i].p = Point(X[i], Y[i]);
    circles[i].r = r - getPadding(H[i]);
  }
  double padding = r - getPadding(W);
  if(2 * padding >= 100) return (false);
  Polygon rectangle(4);
  rectangle[0] = Point(padding, padding);
  rectangle[1] = Point(100 - padding, padding);
  rectangle[2] = Point(100 - padding, 100 - padding);
  rectangle[3] = Point(padding, 100 - padding);

  vector< Point > crossed;
  for(int i = 0; i < N; i++) {
    for(int j = 0; j < i; j++) {
      if(Intersect(circles[i], circles[j])) {
        auto get = Crosspoint(circles[i], circles[j]);
        crossed.push_back(get.first);
        crossed.push_back(get.second);
      }
    }
  }
  for(int j = 0; j < N; j++) {
    for(int i = 0; i < 4; i++) {
      auto seg = Segment(curr(rectangle, i), next(rectangle, i));
      if(Intersect(circles[j], seg)) {
        auto get = Crosspoint(circles[j], seg);
        crossed.push_back(get.first);
        crossed.push_back(get.second);
      }
      crossed.push_back(rectangle[i]);
    }
  }

  for(auto &p : crossed) {
    bool isin = true;
    for(auto &c : circles) {
      isin &= (p - c.p).abs() + 1e-5 >= c.r;
    }
    isin &= Contains(rectangle, p) != OUT;
    if(isin) return (true);
  }
  return (false);
}

int main()
{
  while(scanf("%d %d", &N, &W), N) {
    for(int i = 0; i < N; i++) {
      scanf("%d %d %d", &X[i], &Y[i], &H[i]);
    }
    double low = 0, high = 200;
    for(int i = 0; i < 150; i++) {
      double mid = (low + high) * 0.5;
      if(check(mid)) low = mid;
      else high = mid;
    }
    printf("%.10lf\n", low);
  }
}