Problem: Problem

KND is a student programmer at the University of Aizu. He is known to be a sweet tooth. He will be staying in a city for a year and wants to visit all N sweets shops in the city during that time. So I think the best place to live for the past year is the best place to go around the sweets shop. As his neighbor, you have to find a place that minimizes the worst travel time to each sweets shop. The city where this sweets shop is located is represented by a two-dimensional plane for the sake of simplicity. He travels a different distance per unit time depending on his motivation for the desired sweets shop. He also intends to live anywhere (even in the same place as the sweets shop). KND is uncompromising when it comes to sweetness.

Constraints

The input satisfies the following conditions.

* All inputs are integers.
* 2 ≤ N ≤ 100
* 0 ≤ xi, yi ≤ 100
* 1 ≤ vi ≤ 100 (1 ≤ i ≤ N)
* xi ≠ xj or yi ≠ yj (where 1 ≤ i <j ≤ N)

Input

The input consists of multiple test cases. One test case is given in the following format. Indicates the end of input when N = 0.


N
x1 y1 v1
x2 y2 v2
...
xN yN vN


here,

* N: Number of sweets shops
* xi: x-coordinate of the i-th sweetener
* yi: y coordinate of the i-th sweets shop
* vi: Distance traveled per unit time when moving to the i-th sweets shop



Is.

Output

Output the minimum travel time for each test case on one line. This value should not differ more than 10-5 from the value of the judge output.

Example

Input

2
1 1 1
2 2 1
4
1 1 3
3 1 3
4 2 1
1 5 3
0


Output

0.70710678
1.06066017

Solution (in CPP):

Solution:
#include "bits/stdc++.h"
using namespace std;

//#define int long long
#define DBG 1
#define dump(o) if(DBG){cerr<<#o<<" "<<(o)<<" ";}
#define dumpl(o) if(DBG){cerr<<#o<<" "<<(o)<<endl;}
#define dumpc(o) if(DBG){cerr<<#o; for(auto &e:(o))cerr<<" "<<e;cerr<<endl;}
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define all(c) begin(c),end(c)
const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
const int MOD = (int)(1e9 + 7);
template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (a > b) { a = b; return true; } return false; }

using Weight = double;
class Edge {
public:
	int s; //source
	int d; //destination
	Weight w; //weight
	Edge(int s = 0, int d = 0, Weight w = INF) : s(s), d(d), w(w) {};
	bool operator<(const Edge &e)const { return w < e.w; }
};
using Edges = vector<Edge>;
using Graph = vector<Edges>;
using Array = vector<Weight>;
using Matrix = vector<Array>;
//???????????\
//G[s].emplace_back(s, d, w);
//G[d].emplace_back(d, s, w); ????????¨?????´???


enum { WHITE, GRAY, BLACK }; //?????¢?´¢, ??¢?´¢???, ??¢?´¢???
							 //???????§?????????????(???????????????) Single Source Shortest Path
							 //Dijkstra O((E+V)logV)
							 //dist: ?§????????????????????????§??????????????¢ distance
							 //?????????: ???????????¨????????????(??????-1)
vector<int> dijkstra(const Graph &g, int s, vector<Weight> &dist) {
	using State = tuple<Weight, int, int>; //?§?????????????????°?????????? ??? ???
	priority_queue<State, vector<State>, greater<State>> PQ;
	int n = g.size();
	vector<int> color(n, WHITE);
	vector<int> prev(n, -1);
	dist.assign(n, INF);
	dist[s] = 0; PQ.emplace(0, s, -1); color[s] = GRAY; //?§????
	while (PQ.size()) {
		Weight d; int v, u;
		tie(d, v, u) = PQ.top(); PQ.pop(); //dist???????°???¨??????State???????????????
		if (dist[v] < d)continue; //?????§???????????§???????????°??????
		color[v] = BLACK;
		prev[v] = u;
		for (auto &e : g[v]) { //??£??\????????????????????¨????????????		
			if (color[e.d] == BLACK)continue; //??¢?´¢????????????
			if (dist[e.d] > dist[v] + e.w) {
				dist[e.d] = dist[v] + e.w;
				PQ.emplace(dist[e.d], e.d, v);
				color[e.d] = GRAY;
			}
		}
	}
	return prev;
}

//???????§?????????????(???????????????) Single Source Shortest Path
//Bellman Ford O(VE)
//dist: ?§????????????????????????§??????????????¢
//?????????: ???????????¨????????????, ???????????????:true ??????:false
pair<vector<int>, bool> bellman_ford(const Graph &g, int s, vector<Weight> &dist) {
	int n = g.size();
	vector<int> prev(n, -1);
	Edges es; for (int i = 0; i < n; i++) for (auto &e : g[i]) es.emplace_back(e);
	dist.assign(n, INF); dist[s] = 0;
	bool negative_cycle = false;
	for (int i = 0;; i++) {
		bool update = false;
		for (auto &e : es) {
			if (dist[e.s] != INF && dist[e.d] > dist[e.s] + e.w) {
				dist[e.d] = dist[e.s] + e.w;
				prev[e.d] = e.s;
				update = true;
			}
		}
		if (!update) break;
		if (i > n) { negative_cycle = true; break; }
	}
	return make_pair(prev, !negative_cycle);
}

//?§?????????????????????§??????????????????
//???????????????????????°?????????????§??????????????????§?????????????????¢????????????
//?????¨???????????´???????????????: vector<int>()
vector<int> get_path(int s, int d, vector<int> prev) {
	vector<int> path;
	path.emplace_back(d);
	for (int i = d; i != s; ) {
		if (i == -1)return vector<int>();
		path.emplace_back(i = prev[i]);
	}
	reverse(path.begin(), path.end());
	return path;
}

//??¨????????????????????? All Pairs Shortest Path
//Warshall Floyd O(|V|^3)
//?????????: ???????????????:true ??????:false
bool warshall_floyd(const Graph &g, Matrix &dist) {
	int n = g.size();
	dist.assign(n, Array(n, INF));
	for (int i = 0; i < n; i++) dist[i][i] = 0;
	for (int i = 0; i < n; i++)
		for (auto e : g[i])
			dist[e.s][e.d] = min(dist[e.s][e.d], e.w);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			for (int k = 0; k < n; k++)
				if (dist[j][i] != INF&&dist[i][k] != INF)
					dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);
	bool negative_cycle = false;
	for (int i = 0; i < n; i++)
		if (dist[i][i] != 0)
			negative_cycle = true;
	return !negative_cycle;
}

//??????????????????????????? O(E+V)
//??\?¬???°???0????????¨???????????????????????????ret????????£??????
vector<int> topological_sort(const Graph &g) {
	int n = g.size(), k = 0;
	vector<int> ord(n), indeg(n); //??\?¬???°
	for (auto &es : g) for (auto &e : es) indeg[e.d]++;
	queue<int> Q;
	for (int i = 0; i < n; i++) if (indeg[i] == 0) Q.push(i);
	while (!Q.empty()) {
		int v = Q.front(); Q.pop(); ord[k++] = v;
		for (auto &e : g[v]) if (--indeg[e.d] == 0) Q.push(e.d);
	}
	return *max_element(indeg.begin(), indeg.end()) == 0 ? ord : vector<int>();
}

//??¨?????´???
Edge diameter(const Graph &g, int s = 0) {
	vector<Weight> dist;
	dijkstra(g, s, dist);
	int n = g.size(), u = -1, v = -1;
	for (int i = 0; i < n; i++) if (dist[i] != INF && (u == -1 || dist[i] > dist[u])) u = i;
	dijkstra(g, u, dist);
	for (int i = 0; i < n; i++) if (dist[i] != INF && (v == -1 || dist[i] > dist[v])) v = i;
	Weight d = dist[v];
	if (u > v) swap(u, v);
	return Edge(u, v, d);
}

//#include "UnionFind.cpp"
////????°???¨?????¨
////Kruskal O(|E|log|E|)
//pair<Weight, Edges> kruskal(const Graph &g) {
//	UnionFind UF(g.size());
//	Edges es;
//	for (int i = 0; i < g.size(); i++) for (auto &e : g[i]) es.emplace_back(e);
//	sort(es.begin(), es.end());
//	Weight total = 0;
//	Edges T;
//	for (auto &e : es) if (!UF.same(e.s, e.d)) {
//		T.push_back(e); total += e.w; UF.unite(e.s, e.d);
//	}
//	return make_pair(total, T);
//}
//
////????°???¨?????¨
////Prim O(ElogV)
////r????????°?????????????????????????±?
////Edge??? bool operator<(const Edge &e)const { return w > e.w; } ????????????????????????
//pair<Weight, Edges> prim(const Graph &g, int r = 0) {
//	Edges T; Weight total = 0; vector<int> v(g.size());
//	priority_queue <Edge> q;
//	q.emplace(-1, r, 0);
//	while (q.size()) {
//		Edge e = q.top(); q.pop();
//		if (v[e.d]) continue;
//		v[e.d] = true;
//		total += e.w; if (e.s != -1) T.emplace_back(e);
//		for (auto &f : g[e.d]) if (!v[f.d]) q.emplace(f);
//	}
//	return make_pair(total, T);
//}

//#define double long double
const double EPS = 1e-8; //???????????¨????????´
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define next(P,i) P[(i+1)%P.size()]
#define prev(P,i) P[(i+P.size()-1)%P.size()]

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

	Point operator+(const Point &p)const { return Point(x + p.x, y + p.y); }
	Point operator-(const Point &p)const { return Point(x - p.x, y - p.y); }
	Point operator*(double a)const { return Point(a * x, a * y); }
	Point operator/(double a)const { return Point(x / a, y / a); }
	bool operator<(const Point &p)const {
		//return y != p.y ? y < p.y : x < p.x; // y?????? -> x??????
		return x != p.x ? x < p.x : y < p.y; // x?????? -> y??????
	}
	bool operator==(const Point &p)const { return equals(x, p.x) && equals(y, p.y); }

	double abs() { return sqrt(norm()); }
	double norm() { return x*x + y*y; }
};
inline ostream &operator << (ostream &os, const Point &p) { os << p.x << " " << p.y; return os; }
inline istream &operator >> (istream &is, Point &p) { double x, y; is >> x >> y; p = Point(x, y); return is; }

class Vector :public Point {
public:
	using Point::Point;
	Vector() {}
	Vector(const Point &P) { x = P.x; y = P.y; }
	Vector rotate(double rad) { return Vector(x*cos(rad) - y*sin(rad), x*sin(rad) + y*cos(rad)); }
	Vector unit() { return *this / abs(); }
};

//?????? dot product
double dot(Vector a, Vector b) { return a.x*b.x + a.y*b.y; }
//?????? cross product ?????§???????????£????????????
double cross(Vector a, Vector b) { return a.x*b.y - a.y*b.x; }

class Line {
public:
	Point p1, p2;
	Line() {}
	Line(Point p1, Point p2) :p1(p1), p2(p2) {}
};

class Segment :public Line {
public:
	using Line::Line;
	Segment() {}
	Segment(const Line &L) { p1 = L.p1; p2 = L.p2; }
	Vector vec() { return p2 - p1; }
};

class Circle {
public:
	Point c; //center
	double r; //radius
	Circle() {}
	Circle(Point c, double r) :c(c), r(r) {}
};
using Polygon = vector<Point>;

//?????????????????¢??? degree to radian
double rad(double deg) { return acos(-1)*deg / 180; }
//????§? argument
double arg(Vector p) { return atan2(p.y, p.x); }
//?\???¢??? polar form
Vector polar(double r, double a) { return Point(cos(a)*r, sin(a)*r); }
//2??????????????????????§????
double angle(Vector a, Vector b) {
	double lena = a.abs(), lenb = b.abs();
	if (lena == 0 || lenb == 0)return 0; //?§£??????
	double costheta = dot(a, b) / (lena*lenb);
	if (equals(costheta, 1))costheta = 1; //????????????
	return acos(costheta);
}

bool inrange(Point p, double x1, double y1, double x2, double y2) {
	return x1 <= p.x&&p.x <= x2&&y1 <= p.y&&p.y <= y2;
}

//??´?????????
bool is_orthogonal(Vector a, Vector b) { return equals(dot(a, b), 0.0); }
bool is_orthogonal(Segment s1, Segment s2) { return equals(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0); }

//????????????
bool is_parallel(Vector a, Vector b) { return equals(cross(a, b), 0.0); }
bool is_parallel(Segment s1, Segment s2) { return equals(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0); }

//?°???±
Point project(Segment s, Point p) {
	Vector base = s.p2 - s.p1;
	double r = dot(p - s.p1, base) / base.norm();
	return s.p1 + base*r;
}
//????°?
Point reflect(Segment s, Point p) { return p + (project(s, p) - p)*2.0; }

//??????(p0,p1)????????????p2???????????¢???
enum { ONLINE_FRONT = -2, CLOCKWISE, ON_SEGMENT, COUNTER_CLOCKWISE, ONLINE_BACK };
int ccw(Point p0, Point p1, Point p2) {
	Vector a = p1 - p0, b = p2 - p0;
	if (cross(a, b) > EPS)return COUNTER_CLOCKWISE;
	if (cross(a, b) < -EPS)return CLOCKWISE;
	if (dot(a, b) < -EPS)return ONLINE_BACK; //p2 p0 p1
	if (a.norm() < b.norm())return ONLINE_FRONT; //p0 p1 p2
	return ON_SEGMENT;
}
int ccw(Vector a, Vector b) {
	if (cross(a, b) > EPS)return COUNTER_CLOCKWISE;
	if (cross(a, b) < -EPS)return CLOCKWISE;
	if (dot(a, b) < -EPS)return ONLINE_BACK; //p2 p0 p1
	if (a.norm() < b.norm())return ONLINE_FRONT; //p0 p1 p2
	return ON_SEGMENT;
}

//??´?????¨??´??????????????????
bool intersect(Segment a, Segment b) {
	Point p1 = a.p1, p2 = a.p2, p3 = b.p1, p4 = b.p2;
	return (ccw(p1, p2, p3)*ccw(p1, p2, p4) <= 0 &&
		ccw(p3, p4, p1)*ccw(p3, p4, p2) <= 0);
}
//(?????????????¶????)

//2??????????????¢
double get_distance(Point a, Point b) { return (a - b).abs(); }
//??´?????¨???????????¢
double get_distance(Line l, Point p) { return abs(cross(l.p2 - l.p1, p - l.p1) / (l.p2 - l.p1).abs()); }
//????????¨???????????¢
double get_distance(Segment s, Point p) {
	if (dot(s.p2 - s.p1, p - s.p1) < 0.0)return (p - s.p1).abs();
	if (dot(s.p1 - s.p2, p - s.p2) < 0.0)return (p - s.p2).abs();
	return get_distance(Line(s), p);
}
//????????¨??????????????¢
double get_distance(Segment s1, Segment s2) {
	if (intersect(s1, s2))return 0.0;
	return	min(
		min(get_distance(s1, s2.p1), get_distance(s1, s2.p2)),
		min(get_distance(s2, s1.p1), get_distance(s2, s1.p2))
	);
}

//?????¨??´??????????????????
bool intersect(Circle c, Line l) { return get_distance(l, c.c) <= c.r + EPS; }
//?????¨?????????????????? ??±?????\????????°
int intersect(Circle c1, Circle c2) {
	double d = get_distance(c1.c, c2.c);
	if (d > c1.r + c2.r)return 4;
	if (d == c1.r + c2.r)return 3;
	if (d + c1.r == c2.r || d + c2.r == c1.r)return 1;
	if (d + c1.r < c2.r || d + c2.r < c1.r)return 0;
	return 2;
}

//????????¨???????????????
Point get_cross_point(Segment a, Segment b) {
	assert(intersect(a, b));
	Vector base = b.p2 - b.p1;
	double area1 = abs(cross(base, a.p1 - b.p1));
	double area2 = abs(cross(base, a.p2 - b.p1));
	double t = area1 / (area1 + area2);
	return a.p1 + (a.p2 - a.p1)*t;
}

//?????¨??´????????????
pair<Point, Point> get_cross_points(Circle c, Line l) {
	assert(intersect(c, l));
	Vector pr = project(l, c.c);
	Vector e = (l.p2 - l.p1) / (l.p2 - l.p1).abs();
	double base = sqrt(c.r*c.r - (pr - c.c).norm());
	return make_pair(pr + e*base, pr - e*base);
}
//?????¨????????????
pair<Point, Point> get_cross_points(Circle c1, Circle c2) {
	int m = intersect(c1, c2);
	assert(m != 4 && m != 0);
	double d = (c1.c - c2.c).abs();
	double a = acos((c1.r*c1.r + d*d - c2.r*c2.r) / (2 * c1.r*d));
	double t = arg(c2.c - c1.c);
	return make_pair(c1.c + polar(c1.r, t + a), c1.c + polar(c1.r, t - a));
}

//????????????
enum { OUT = 0, ON, IN };
int contains(const Polygon &pl, Point p) {
	int n = pl.size();
	bool x = false;
	for (int i = 0; i < n; i++) {
		Point a = pl[i] - p, b = pl[(i + 1) % n] - p;
		if (abs(cross(a, b)) < EPS&&dot(a, b) < EPS)return ON;
		if (a.y > b.y)swap(a, b);
		if (a.y < EPS&&EPS<b.y&&cross(a, b)>EPS)x = !x;
	}
	return (x ? IN : OUT);
}

int contains(Circle c, Point p) {
	double d = get_distance(c.c, p);
	if (equals(d, c.r))return ON;
	if (d < c.r)return IN;
	return OUT;
}

//????§???¢?????¢???
double area(const Polygon &p) {
	double a = 0;
	for (size_t i = 0; i < p.size(); i++)
		a += cross(p[i], p[(i + 1) % p.size()]);
	return a / 2.0;
}

//?????§????????????????¨??????????
bool is_convex(Polygon g) {
	for (size_t i = 0; i < g.size(); i++)
		if (ccw(g[i], g[(i + 1) % g.size()], g[(i + 2) % g.size()]) == CLOCKWISE)
			return false;
	return true;
}

//??????
//Graham scan https://en.wikipedia.org/wiki/Graham_scan
//???????????????????????????
Polygon convex_hull(Polygon P) {
	sort(P.begin(), P.end());
	Polygon up;
	for (Point &p : P) {
		while (up.size() > 1 && ccw(up[up.size() - 2], up[up.size() - 1], p) != CLOCKWISE)up.pop_back();
		up.emplace_back(p);
	}
	Polygon down;
	for (Point &p : P) {
		while (down.size() > 1 && ccw(down[down.size() - 2], down[down.size() - 1], p) != COUNTER_CLOCKWISE)down.pop_back();
		down.emplace_back(p);
	}
	reverse(up.begin(), up.end()); // ???????¨??????????
	down.insert(down.end(), up.begin() + 1, up.end() - 1);
	return down;
}

//??????
//Graham scan https://en.wikipedia.org/wiki/Graham_scan
//?????????????????????
Polygon convex_hull_with_points_online(Polygon P) {
	sort(P.begin(), P.end());
	Polygon up;
	for (Point &p : P) {
		int _ccw;
		while (up.size() > 1 && (_ccw = ccw(up[up.size() - 2], up[up.size() - 1], p)) != CLOCKWISE &&_ccw != ONLINE_FRONT)
			up.pop_back();
		up.emplace_back(p);
	}
	Polygon down;
	for (Point &p : P) {
		int _ccw;
		while (down.size() > 1 && (_ccw = ccw(down[down.size() - 2], down[down.size() - 1], p)) != COUNTER_CLOCKWISE && _ccw != ONLINE_FRONT)
			down.pop_back();
		down.emplace_back(p);
	}
	reverse(up.begin(), up.end()); // ???????¨??????????
	down.insert(down.end(), up.begin() + 1, up.end() - 1);
	return down;
}

//???????§???¢??????????????????????????¢
//calipers https://en.wikipedia.org/wiki/Rotating_calipers
double diameter(Polygon P) {
	P = convex_hull(P);
	auto mima = minmax_element(P.begin(), P.end());
	int I = mima.first - P.begin();
	int J = mima.second - P.begin();
	double maxd = get_distance(P[I], P[J]);

	int maxi, maxj, i, j;
	i = maxi = I;
	j = maxj = J;
	do {
		if (ccw(next(P, i) - P[i], next(P, j) - P[j]) == COUNTER_CLOCKWISE)
			j = (j + 1) % P.size();
		else
			i = (i + 1) % P.size();
		if (maxd < get_distance(P[i], P[j])) {
			maxd = get_distance(P[i], P[j]);
			maxi = i, maxj = j;
		}
	} while (!(i == I&&j == J));
	return maxd;
}

//????§???¢???(0,0)???????????¨???????????¢
Polygon rotate(const Polygon &P, double rad) {
	Polygon ret;
	for (auto &p : P)
		ret.emplace_back(p.x*cos(rad) - p.y*sin(rad), p.x*sin(rad) + p.y*cos(rad));
	return ret;
}

//Heron's formula
double area(double a, double b, double c) {
	double s = (a + b + c) / 2;
	return sqrt(s*(s - a)*(s - b)*(s - c));
}

//????§???¢?????????
Point center(const Polygon &P) {
	Point ret(0, 0);
	for (auto &p : P)ret = ret + p;
	ret = ret / P.size();
	return ret;
}

signed main() {
	cout << fixed << setprecision(8);
	for (int n; cin >> n&&n;) {
		vector<Point> p(n);
		vector<double> v(n);
		rep(i, 0, n) cin >> p[i] >> v[i];

		double r = 0.98;
		Point o(0, 0);

		auto calc = [&](Point o) {
			auto mx = make_pair(0.0, 0);
			rep(i, 0, n) mx = max(mx, make_pair((o - p[i]).abs() / v[i], i));
			return mx;
		};

		for (double d = 10; d > 1e-8; d *= r) {
			auto mx = calc(o).second;
			o = o + (p[mx] - o) / (p[mx] - o).abs() * d;
		}
		cout << calc(o).first << endl;
	}
	return 0;
}