#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const long long __64inf = 0x3f3f3f3f3f3f3f3f;
const int MAX = 1e6 + 50;
const int mod = 998244353;
void file_read() {}
struct Seg {
  double xl, xr, y;
  Seg(double xl, double xr, double y) : xl(xl), xr(xr), y(y) {}
};
vector<Seg> seg;
vector<pair<double, double>> bd;
void bound() {
  for (int i = 0; i < seg.size(); i++) {
    for (int j = i + 1; j < seg.size(); j++) {
      if (seg[i].y == seg[j].y) continue;
      auto s1 = seg[i];
      auto s2 = seg[j];
      if (s1.y > s2.y) swap(s1, s2);
      double beta1 = (s1.xr - s2.xl) / (s2.y - s1.y);
      double beta2 = (s1.xl - s2.xr) / (s2.y - s1.y);
      bd.emplace_back(beta2, beta1);
    }
  }
}
void filter(vector<double> &theta) {
  double cur = -__64inf;
  for (auto x : bd) {
    if (x.first >= cur) {
      theta.push_back(x.first);
      if (cur > -__64inf) theta.push_back(cur);
    }
    cur = max(cur, x.second);
  }
  theta.push_back(cur);
}
double cross(pair<double, double> A, pair<double, double> B) {
  return (A.first - B.first) / (B.second - A.second);
}
template <typename Cmp_1, typename Cmp_2>
struct Convex {
  int top;
  vector<pair<double, double>> pts;
  vector<double> X;
  pair<double, double> stk[3000];
  Cmp_1 cmp_1;
  Cmp_2 cmp_2;
  Convex(vector<Seg> &seg) : cmp_1(Cmp_1()), cmp_2(Cmp_2()) {
    for (auto s : seg) {
      pts.emplace_back(s.xl, s.y);
      pts.emplace_back(s.xr, s.y);
    }
    sort(pts.begin(), pts.end(),
         [this](const pair<double, double> &A, const pair<double, double> &B) {
           if (abs(A.second - B.second) < 1e-8)
             return this->cmp_1(A.first, B.first);
           return this->cmp_2(A.second, B.second);
         });
    int i = 0;
    top = 0;
    stk[top++] = pts[0];
    while (i < pts.size() and abs(pts[i].second - pts[0].second) < 1e-8) i++;
    if (i == pts.size()) {
      X.push_back(-__64inf);
      return;
    }
    stk[top++] = pts[i++];
    while (i < pts.size()) {
      int j = i;
      while (j < pts.size() and abs(pts[j].second - pts[i].second) < 1e-8) j++;
      if (j == pts.size()) break;
      auto cur = pts[j];
      while (top >= 2) {
        double cross_x = cross(stk[top - 1], stk[top - 2]);
        double cross_cur = cross(cur, stk[top - 2]);
        if (cross_cur < cross_x)
          top--;
        else
          break;
      }
      stk[top++] = cur;
      i = j + 1;
    }
    X.push_back(-__64inf);
    for (int i = 1; i < top; i++) {
      X.push_back(cross(stk[i - 1], stk[i]));
    }
  }
  double query(double a) {
    int idx = lower_bound(X.begin(), X.end(), a) - X.begin();
    idx--;
    return stk[idx].first + stk[idx].second * a;
  }
};
struct Less {
  bool operator()(double A, double B) { return A < B; }
};
struct Great {
  bool operator()(double A, double B) { return A > B; }
};
int main() {
  int n;
  scanf("%d", &n);
  set<double> Y;
  for (int i = 0; i < n; i++) {
    double xl, xr, y;
    scanf("%lf%lf%lf", &xl, &xr, &y);
    seg.emplace_back(xl, xr, y);
    Y.insert(y);
  }
  if (Y.size() == 1) {
    double Min = __64inf, Max = -__64inf;
    for (auto s : seg) {
      Min = min(s.xl, Min);
      Max = max(Max, s.xr);
    }
    printf("%.10f\n", Max - Min);
    return 0;
  }
  bound();
  vector<double> theta;
  sort(bd.begin(), bd.end());
  filter(theta);
  double ans = __64inf;
  Convex<Less, Great> left(seg);
  Convex<Great, Less> right(seg);
  for (auto x : theta) {
    double l = left.query(x);
    double r = right.query(x);
    ans = min(ans, r - l);
  }
  printf("%.10f\n", ans);
}
