#include <bits/stdc++.h>
using namespace std;
int const maxn = 1e5 + 10, maxk = 30;
int n, m, x[maxn], y[maxn], l[maxn];
multiset<int> tree;
multiset<int>::iterator it;
struct pii {
  int x, ini, fim, type;
  pii(int a, int b, int c, int d) : x(a), ini(b), fim(c), type(d) {}
};
vector<pii> p;
bool compare(pii a, pii b) {
  return a.x < b.x || (a.x == b.x && a.type < b.type);
}
bool solve(int k) {
  p.clear();
  tree.clear();
  for (int i = 1; i <= n; i++) {
    int Y1 = y[i] + k, Y2 = y[i] + l[i] - k;
    if (Y1 > Y2) continue;
    p.push_back(pii(x[i], Y1, Y2, 1));
  }
  for (int i = 1; i <= m; i++) {
    int X1 = x[n + i] + k, X2 = x[n + i] + l[n + i] - k;
    if (X1 > X2) continue;
    p.push_back(pii(X1, -1, y[n + i], 0));
    p.push_back(pii(X2, -1, y[n + i], 2));
  }
  sort(p.begin(), p.end(), compare);
  for (int i = 0; i < p.size(); i++) {
    int type = p[i].type;
    if (type == 0) {
      int Y = p[i].fim;
      tree.insert(Y);
    }
    if (type == 2) {
      int Y = p[i].fim;
      it = tree.find(Y);
      tree.erase(it);
    }
    if (type == 1) {
      int ini = p[i].ini, fim = p[i].fim;
      it = tree.lower_bound(ini);
      if (it == tree.end()) continue;
      if (*it > fim) continue;
      return true;
    }
  }
  return false;
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%d%d%d", &x[i], &y[i], &l[i]);
  for (int i = 1; i <= m; i++) scanf("%d%d%d", &x[n + i], &y[n + i], &l[n + i]);
  int ini = 0, fim = 1e8;
  for (int i = 1; i < maxk; i++) {
    int mid = (ini + fim) / 2;
    bool cmp = solve(mid);
    if (cmp)
      ini = mid;
    else
      fim = mid;
  }
  printf("%d \n", ini);
}
