#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define sd(x) scanf("%d", &(x))
#define pii pair<int, int>
#define F first
#define S second
#define all(c) ((c).begin()), ((c).end())
#define sz(x) ((int)(x).size())
#define ld long double

template<class T,class U>
ostream& operator<<(ostream& os,const pair<T,U>& p){
	os<<"("<<p.first<<", "<<p.second<<")";
	return os;
}

template<class T,class U>
ostream& operator<<(ostream& os,const map<T, U> & mp){
	os << "{";
	int i = 0;
	for(auto it : mp){
		if(i) os<<", ";
		os << it;
		i++;
	}
	os << "}";	
	return os;
}

template<class T>
ostream& operator <<(ostream& os,const vector<T>& v){
	os<<"{";
	for(int i = 0;i < (int)v.size(); i++){
		if(i)os<<", ";
		os<<v[i];
	}
	os<<"}";
	return os;
}

#ifdef LOCAL
#define cerr cout
#else
#endif

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

struct graph {
  int L, R;
  vector<vector<int>> adj;
  set<pii> edges;
  graph(int L, int R) : L(L), R(R), adj(L+R) { }
  void add_edge(int u, int v) {

	  pii X = {u, v};
	  if(edges.count(X)) return;
	  edges.insert(X);
    adj[u].push_back(v+L);
    adj[v+L].push_back(u);

  }
  vector<int> maximum_matching() {
    vector<int> level(L), mate(L+R, -1);
    queue<int> Q;
    function<bool(void)> levelize = [&]() { // BFS
    //   Q.re_init_indices();
      for (int u = 0; u < L; ++u) {
        level[u] = -1;
        if (mate[u] < 0) {
          level[u] = 0;
          Q.push(u); 
        }
      }
      while (!Q.empty()) {
        int u = Q.front();
		Q.pop();
        for (int w: adj[u]) {
          int v = mate[w];
          if (v < 0) return true;
          if (level[v] < 0) {
            level[v] = level[u] + 1;
            Q.push(v); 
          }
        }
      }
      return false;
    };
    function<bool(int)> augment = [&](int u) { // DFS
      for (int w: adj[u]) {
        int v = mate[w];
        if (v < 0 || (level[v] > level[u] && augment(v))) {
          mate[u] = w;
          mate[w] = u;
          return true;
        }
      }
      return false;
    };
    int match = 0;
    while (levelize()) 
      for (int u = 0; u < L; ++u) 
        if (mate[u] < 0 && augment(u)) 
          ++match;
    return mate;
  }
};
const int N = 105;
int A[N][N];
void printA(int n, int m){
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			printf("%d ", A[i][j] + 1);
		}
		printf("\n");
	}
}

int B[N][N], C[N][N];
int main(){
	int n, m;
	sd(n); sd(m);
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			sd(A[i][j]);
			A[i][j]--;
		}
	}

	for(int i = 0; i < m; i++){
		graph g(n, n);
		for(int j = 0; j < n; j++){
			for(int k = i; k < m; k++){
				g.add_edge(j, A[j][k] / m);
			}
		}

		vector<int> M = g.maximum_matching();
		// assert(0);
		for(int j = 0; j < n; j++){
			int mj = M[j];
			for(int k = i; k < m; k++) if(A[j][k] / m == mj - n){
				swap(A[j][i], A[j][k]);
				break;
			}
		}
	}
	printA(n,m);
	for(int i = 0; i < m;i++){
		vector<int> X;
		for(int j = 0; j < n; j++) X.push_back(A[j][i]);
		sort(all(X));
		for(int j = 0; j < n; j++) A[j][i] = X[j];
	}
	printA(n, m);
}

Measured memory_bytes: 896