Problem: After returning to shore, uncle Bogdan usually visits the computer club "The Rock", to solve tasks in a pleasant company. One day, uncle Bogdan met his good old friend who told him one unusual task...

There are n non-intersecting horizontal segments with ends in integers points on the plane with the standard cartesian coordinate system. All segments are strictly above the OX axis. You can choose an arbitrary vector (a, b), where b < 0 and coordinates are real numbers, and project all segments to OX axis along this vector. The projections shouldn't intersect but may touch each other.

Find the minimum possible difference between x coordinate of the right end of the rightmost projection and x coordinate of the left end of the leftmost projection.

Input

The first line contains the single integer n (1 ≤ n ≤ 2000) — the number of segments.

The i-th of the next n lines contains three integers xl_i, xr_i and y_i (-10^6 ≤ xl_i < xr_i ≤ 10^6; 1 ≤ y_i ≤ 10^6) — coordinates of the corresponding segment.

It's guaranteed that the segments don't intersect or touch.

Output

Print the minimum possible difference you can get.

Your answer will be considered correct if its absolute or relative error doesn't exceed 10^{-6}.

Formally, if your answer is a and jury's answer is b then your answer will be considered correct if \frac{|a - b|}{max{(1, |b|)}} ≤ 10^{-6}.

Examples

Input


3
1 6 2
4 6 4
4 6 6


Output


9.000000000


Input


3
2 5 1
4 6 4
7 8 2


Output


6.333333333


Input


2
1 3 1
4 7 1


Output


6.000000000

Note

In the first example if we project segments along the vector (1, -1) then we get an answer 12-3=9 and (it can be proven) it is impossible to get less. 

<image>

It is optimal to project along the vector (1, -3) in the second example. The answer is 82/3-21/3=61/3 

<image>

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
#pragma GCC optimize("O3")
using namespace std;
template <class T>
inline void amin(T &x, const T &y) {
  if (y < x) x = y;
}
template <class T>
inline void amax(T &x, const T &y) {
  if (x < y) x = y;
}
template <class Iter>
void rprintf(const char *fmt, Iter begin, Iter end) {
  for (bool sp = 0; begin != end; ++begin) {
    if (sp)
      putchar(' ');
    else
      sp = true;
    printf(fmt, *begin);
  }
  putchar('\n');
}
struct IntPoint {
  long long x, y;
  IntPoint() { x = y = 0; }
  IntPoint(long long x_, long long y_) {
    x = x_;
    y = y_;
  }
  IntPoint &operator+=(const IntPoint &r) {
    x += r.x;
    y += r.y;
    return *this;
  }
  IntPoint &operator-=(const IntPoint &r) {
    x -= r.x;
    y -= r.y;
    return *this;
  }
  IntPoint &operator*=(const IntPoint &r) { return *this = *this * r; }
  IntPoint operator-() const { return IntPoint(-x, -y); }
  friend IntPoint operator+(IntPoint l, const IntPoint &r) { return l += r; }
  friend IntPoint operator-(IntPoint l, const IntPoint &r) { return l -= r; }
  friend IntPoint operator*(const IntPoint &l, const IntPoint &r) {
    return IntPoint(l.x * r.x - l.y * r.y, l.x * r.y + l.y * r.x);
  }
  friend bool operator<(const IntPoint &l, const IntPoint &r) {
    return l.x != r.x ? l.x < r.x : l.y < r.y;
  }
  friend bool operator>(const IntPoint &l, const IntPoint &r) { return r < l; }
  friend bool operator<=(const IntPoint &l, const IntPoint &r) {
    return !(r < l);
  }
  friend bool operator>=(const IntPoint &l, const IntPoint &r) {
    return !(l < r);
  }
  friend bool operator==(const IntPoint &l, const IntPoint &r) {
    return l.x == r.x && l.y == r.y;
  }
  friend bool operator!=(const IntPoint &l, const IntPoint &r) {
    return !(l == r);
  }
};
const IntPoint ZERO = IntPoint();
long long dot(const IntPoint &l, const IntPoint &r) {
  return l.x * r.x + l.y * r.y;
}
long long cross(const IntPoint &l, const IntPoint &r) {
  return l.x * r.y - l.y * r.x;
}
int ccw(const IntPoint &a, IntPoint b, IntPoint c) {
  b -= a;
  c -= a;
  long long l = b.x * c.y;
  long long r = b.y * c.x;
  if (l < r) return -1;
  if (l > r) return 1;
  return 0;
}
int ccw_zero(const IntPoint &b, const IntPoint &c) {
  long long l = b.x * c.y;
  long long r = b.y * c.x;
  if (l < r) return -1;
  if (l > r) return 1;
  return 0;
}
IntPoint rot90(const IntPoint &p) { return IntPoint(-p.y, p.x); }
IntPoint rot270(const IntPoint &p) { return IntPoint(p.y, -p.x); }
enum class Orthant { O, L, LD, D, RD, R, RU, U, LU };
Orthant orthant(const IntPoint &p) {
  if (p.x == 0 && p.y == 0) return Orthant::O;
  if (p.x < 0 && p.y == 0) return Orthant::L;
  if (p.x < 0 && p.y < 0) return Orthant::LD;
  if (p.x == 0 && p.y < 0) return Orthant::D;
  if (p.x > 0 && p.y < 0) return Orthant::RD;
  if (p.x > 0 && p.y == 0) return Orthant::R;
  if (p.x > 0 && p.y > 0) return Orthant::RU;
  if (p.x == 0 && p.y > 0) return Orthant::U;
  if (p.x < 0 && p.y > 0) return Orthant::LU;
  assert(false);
}
namespace SORT_BY_ARG {
IntPoint buf[100011];
void sort_by_arg(IntPoint *a, IntPoint *end) {
  int n = end - a;
  int c[9] = {}, d[9] = {};
  for (int i = 0, i_len = (n); i < i_len; ++i) c[(int)orthant(a[i])]++;
  for (int t = 0, t_len = (8); t < t_len; ++t) d[t + 1] = d[t] + c[t];
  for (int i = 0, i_len = (n); i < i_len; ++i)
    buf[d[(int)orthant(a[i])]++] = a[i];
  for (int t = 2; t <= 8; t += 2) {
    sort(buf + d[t - 1], buf + d[t],
         [](const IntPoint &l, const IntPoint &r) { return cross(l, r) > 0; });
  }
  for (int i = 0, i_len = (n); i < i_len; ++i) a[i] = buf[i];
}
void sort_by_arg_idx(IntPoint *a, IntPoint *end, int *idx) {
  int n = end - a;
  int c[9] = {}, d[9] = {};
  for (int i = 0, i_len = (n); i < i_len; ++i) c[(int)orthant(a[i])]++;
  for (int t = 0, t_len = (8); t < t_len; ++t) d[t + 1] = d[t] + c[t];
  for (int i = 0, i_len = (n); i < i_len; ++i) idx[d[(int)orthant(a[i])]++] = i;
  for (int t = 2; t <= 8; t += 2) {
    sort(idx + d[t - 1], idx + d[t],
         [&](int i, int j) { return cross(a[i], a[j]) > 0; });
  }
}
};  // namespace SORT_BY_ARG
struct ByArg {
  int cmp(const IntPoint &l, const IntPoint &r) const {
    if (l == r) return 0;
    if (l.x == 0 && l.y == 0) return -1;
    if (r.x == 0 && r.y == 0) return 1;
    Orthant lval = orthant(l), rval = orthant(r);
    if (lval != rval) return lval < rval ? -1 : 1;
    switch (lval) {
      case Orthant::O:
      case Orthant::L:
      case Orthant::D:
      case Orthant::R:
      case Orthant::U:
        return 0;
      default:
        break;
    }
    return ccw_zero(r, l);
  }
  bool operator()(const IntPoint &l, const IntPoint &r) const {
    return cmp(l, r) < 0;
  }
} byArg;
struct Data {
  IntPoint p;
  int add;
  Data() {}
  Data(const IntPoint p_, int add_) : p(p_), add(add_) {}
  bool operator<(const Data &o) const { return ByArg()(p, o.p); }
};
template <class Iter>
vector<IntPoint> convex_hull(Iter a, Iter a_end, bool allow_180 = false) {
  int n = a_end - a, len = 0;
  assert(n >= 3);
  sort(a, a_end);
  vector<IntPoint> h(n * 2);
  const int allow = (allow_180 ? 0 : 1);
  for (int i = 0, i_len = (n); i < i_len; ++i) {
    while (len >= 2 && ccw(h[len - 2], h[len - 1], a[i]) < allow) len--;
    h[len++] = a[i];
  }
  for (int i = n - 2, t = len + 1; i >= 0; i--) {
    while (len >= t && ccw(h[len - 2], h[len - 1], a[i]) < allow) len--;
    h[len++] = a[i];
  }
  h.resize(len - 1);
  return h;
}
double eval(const IntPoint &p, const IntPoint &v) {
  double rate = (double)p.y / -v.y;
  return p.x + v.x * rate;
}
const int MAXN = 2011;
int N;
long long XL[MAXN], XR[MAXN], Y[MAXN];
bool line() { return *min_element(Y, Y + N) == *max_element(Y, Y + N); }
void MAIN() {
  scanf("%d", &N);
  for (int i = 0, i_len = (N); i < i_len; ++i)
    scanf("%lld%lld%lld", XL + i, XR + i, Y + i);
  if (line()) {
    long long ans = *max_element(XR, XR + N) - *min_element(XL, XL + N);
    printf("%lld\n", ans);
    return;
  }
  vector<Data> V;
  for (int i = 0, i_len = (N); i < i_len; ++i)
    for (int j = 0, j_len = (N); j < j_len; ++j)
      if (Y[i] < Y[j]) {
        IntPoint a(XR[i] - XL[j], Y[i] - Y[j]);
        IntPoint b(XL[i] - XR[j], Y[i] - Y[j]);
        V.emplace_back(b, 1);
        V.emplace_back(a, -1);
      }
  sort(V.begin(), V.end());
  vector<IntPoint> VECS;
  int sum = 0;
  for (int i = 0; i < (int)V.size();) {
    int j = i;
    IntPoint p = V[i].p;
    while (j < (int)V.size() && cross(p, V[j].p) == 0) {
      j++;
    }
    for (int k = i; k < j; k++) {
      if (V[k].add < 0) sum += V[k].add;
    }
    if (sum == 0) {
      VECS.push_back(p);
    }
    for (int k = i; k < j; k++) {
      if (V[k].add > 0) sum += V[k].add;
    }
    if (sum == 0) {
      VECS.push_back(p);
    }
    i = j;
  }
  vector<IntPoint> PS;
  for (int i = 0, i_len = (N); i < i_len; ++i) {
    PS.emplace_back(XL[i], Y[i]);
    PS.emplace_back(XR[i], Y[i]);
  }
  PS = convex_hull(PS.begin(), PS.end());
  vector<double> ans(VECS.size(), 0.0);
  for (int t = 0, t_len = (2); t < t_len; ++t) {
    int sgn = (t ? 1 : -1);
    int index = 0;
    for (int i = 0, i_len = (VECS.size()); i < i_len; ++i) {
      const IntPoint &v = VECS[i];
      double best = sgn * eval(PS[index], v);
      while (1) {
        int left = index - 1;
        if (left < 0) left += PS.size();
        double tmp = sgn * eval(PS[left], v);
        if (best < tmp) {
          index = left;
          best = tmp;
        } else {
          break;
        }
      }
      while (1) {
        int right = index + 1;
        if (right >= (int)PS.size()) right -= PS.size();
        double tmp = sgn * eval(PS[right], v);
        if (best < tmp) {
          index = right;
          best = tmp;
        } else {
          break;
        }
      }
      ans[i] += best;
    }
  }
  printf("%.20f\n", *min_element(ans.begin(), ans.end()));
}
int main() {
  int TC = 1;
  for (int tc = 0, tc_len = (TC); tc < tc_len; ++tc) MAIN();
  return 0;
}