#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 16 + 2, MAX_M = 10 * 1000, MAX_MASK = (1 << 16) + 10;
int n, m, a[MAX_N][MAX_M], adj[MAX_N], dp[MAX_MASK][MAX_N][MAX_N];
void read_input() {
  cin >> n >> m;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) cin >> a[i][j];
}
bool is_ok_rows(int x, int y, int k) {
  for (int i = 0; i < m; i++)
    if (abs(a[x][i] - a[y][i]) < k) return false;
  return true;
}
void build_graph(int k) {
  for (int i = 0; i < n; i++) {
    adj[i] = 0;
    for (int j = 0; j < n; j++)
      if (is_ok_rows(i, j, k)) adj[i] |= 1 << j;
  }
}
bool is_ok2(int x, int y, int k) {
  for (int i = 1; i < m; i++)
    if (abs(a[x][i] - a[y][i - 1]) < k) return false;
  return true;
}
bool check(int k) {
  build_graph(k);
  memset(dp, 0, sizeof dp);
  for (int v = 0; v < n; v++) dp[1 << v][v][v] = true;
  for (int mask = 0; mask < 1 << n; mask++)
    if (__builtin_popcount(mask) > 1)
      for (int v = 0; v < n; v++)
        if (mask >> v & 1)
          for (int u = 0; u < n; u++)
            if (mask >> u & 1)
              for (int w = 0; w < n; w++)
                if (adj[v] >> w & 1)
                  dp[mask][v][u] |= dp[mask ^ (1 << v)][w][u];
  bool res = false;
  for (int v = 0; v < n; v++)
    for (int u = 0; u < n; u++)
      if (is_ok2(u, v, k)) res |= dp[(1 << n) - 1][v][u];
  return res;
}
void solve() {
  int L = 0, R = 1e9 + 10;
  while (L < R - 1) {
    int mid = (L + R) / 2;
    if (check(mid))
      L = mid;
    else
      R = mid;
  }
  cout << L;
}
int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  read_input();
  solve();
}
