#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("-Ofast")
#pragma GCC optimize("trapv")
#pragma GCC target( \
    "sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
const int N = 17;
const int M = 10005;
long long int expo_pow(long long int x, long long int y) {
  if (y == 0) return 1;
  y = y % ((1000000007) - 1);
  x %= (1000000007);
  if (y == 0) y = (1000000007) - 1;
  long long int res = 1;
  while (y) {
    if (y & 1) res = (res * x) % (1000000007);
    x = (x * x) % (1000000007);
    y >>= 1;
  }
  return res;
}
long long int modInverse(long long int a, long long int m = (1000000007)) {
  return expo_pow(a, m - 2);
}
void dfs(int v, vector<int> &visited, vector<vector<int> > &adj,
         vector<int> &ans) {
  visited[v] = true;
  for (int u : adj[v]) {
    if (!visited[u]) dfs(u, visited, adj, ans);
  }
  ans.push_back(v);
}
void topological_sort(vector<vector<int> > &adj, vector<int> &visited,
                      vector<int> &ans, int n) {
  ans.clear();
  for (int i = 1; i <= n; ++i) {
    if (!visited[i]) dfs(i, visited, adj, ans);
  }
  reverse(ans.begin(), ans.end());
}
int n, m;
int a[N][M], store[N][N], store2[N][N];
int cache[N][1 << (N - 1)][N];
int dp(int start, int mask, int prev) {
  if ((mask + 1) == (1 << n)) return 1e9;
  int &ans = cache[start][mask][prev];
  if (ans != -1) return ans;
  ans = 0;
  int cnt = __builtin_popcount(mask);
  for (int i = 0; i < n; i++) {
    if (mask >> i & 1) continue;
    int prv = prev + 1;
    int nxt = i + 1;
    int cur = min(store[prv][nxt], dp(start, mask | (1 << i), i));
    if (cnt == n - 1) cur = min(cur, store2[start + 1][nxt]);
    ans = max(ans, cur);
  }
  return ans;
}
void solve() {
  memset(cache, -1, sizeof(cache));
  cin >> n >> m;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) cin >> a[i][j];
  if (n == 1) {
    int ans = 1e9;
    for (int i = 1; i <= m - 1; i++) ans = min(ans, abs(a[1][i] - a[1][i + 1]));
    cout << ans;
    return;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      store[i][j] = 1e9;
      if (i == j) continue;
      for (int k = 1; k <= m; k++)
        store[i][j] = min(store[i][j], abs(a[i][k] - a[j][k]));
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      store2[i][j] = 1e9;
      if (i == j) continue;
      for (int k = 1; k <= m - 1; k++)
        store2[i][j] = min(store2[i][j], abs(a[i][k] - a[j][k + 1]));
    }
  }
  int ans = 0;
  for (int i = 0; i < n; i++) ans = max(ans, dp(i, (1 << i), i));
  cout << ans;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int T = 1;
  while (T--) {
    solve();
  }
}
