#include <bits/stdc++.h>
using namespace std;
#define pb push_back
const int N=105;
int a[N][N],n,m;
bool was[N][N];
void rot(int x)
{
	int tmp=a[x][1];
	for(int i=2;i<=m;i++) a[x][i-1]=a[x][i];
	a[x][m]=tmp;
}
void SolveRow(int x)
{
	sort(a[x]+1,a[x]+1+m);
	int cnt=0;
	while(1)
	{
		bool ok=1;
		for(int i=1;i<=m;i++) if(was[i][(a[x][i]-1)/m]){ ok=0;break;}
		if(ok) break;
		rot(x);
		cnt++;
		assert(cnt!=m);
	}
	for(int i=1;i<=m;i++) was[i][(a[x][i]-1)/m]=1;
}
void SortCol(int y)
{
	vector<int> tmp;
	for(int i=1;i<=n;i++) tmp.pb(a[i][y]);
	sort(tmp.begin(),tmp.end());
	for(int i=1;i<=n;i++) a[i][y]=tmp[i-1];
}
int cnt[N][N];
vector<int> my[N][N];
bool use[N],cws[N];
struct Edge
{
	int u,v,c;
	Edge(){}
	Edge(int a, int b, int d):u(a),v(b),c(d){}
};
vector<Edge> edges;
int s,t;
const int M=2*N;
vector<int> G[M];
void AddEdge(int u, int v)
{
	G[u].pb(edges.size());
	edges.pb(Edge(u,v,1));
	G[v].pb(edges.size());
	edges.pb(Edge(v,u,0));
}
int go[M];
bool bfs_was[M];
bool BFS()
{
	for(int i=s;i<=t;i++) bfs_was[i]=0;
	bfs_was[s]=1;
	queue<int> q;
	q.push(s);
	while(q.size())
	{
		int u=q.front();
		q.pop();
		for(int e:G[u])
		{
			int v=edges[e].v;
			int c=edges[e].c;
			if(c && !bfs_was[v])
			{
				bfs_was[v]=1;
				q.push(v);
				go[v]=e;
			}
		}
	}
	return bfs_was[t];
}
vector<int> Matching()
{
	int Flow=0;
	while(BFS())
	{
		for(int i=t;i!=s;i=edges[go[i]].u)
		{
			edges[go[i]].c--;
			edges[go[i]^1].c++;
		}
		Flow++;
	}
	if(Flow!=n)
	{
		while(clock()<15*CLOCKS_PER_SEC) n++;
	}
	vector<int> ans(n,0);
	for(Edge E:edges)
	{
		if(E.u==s || E.v==t) continue;
		if(E.u<=n && E.v>n && E.c==0) ans[E.u-1]=E.v-n-1;
	}
	return ans;
}
void Clear()
{
	for(int i=s;i<=t;i++) G[i].clear();
	edges.clear();
}
void Solve()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cnt[i][(a[i][j]-1)/m]++;
			my[i][(a[i][j]-1)/m].pb(a[i][j]);
		}
	}
	s=0;t=2*n+1;
	for(int j=1;j<=m;j++)
	{
		//for(int i=0;i<=n;i++) use[i]=0,cws[i]=0;
		Clear();
		for(int k=0;k<n;k++)
		{
			AddEdge(n+k+1,t);
			AddEdge(s,k+1);
			for(int i=1;i<=n;i++) if(cnt[i][k]>0) AddEdge(i,n+k+1);
			/*int mx=-1;
			for(int i=1;i<=n;i++) if(!cws[i])
			{
				if(mx==-1 || cnt[i][k]>cnt[mx][k]) mx=i;
			}
			assert(cnt[mx][k]!=0);
			a[mx][j]=my[mx][k].back();
			my[mx][k].pop_back();
			cnt[mx][k]--;
			cws[mx]=1;
			printf("a[%i][%i]=%i\n",mx,j,a[mx][j]);*/
		}
		vector<int> ans=Matching();
		for(int i=1;i<=n;i++)
		{
			a[i][j]=my[i][ans[i-1]].back();
			my[i][ans[i-1]].pop_back();
			cnt[i][ans[i-1]]--;
			//printf("a[%i][%i]=%i\n",i,j,a[i][j]);
		}
		/*for(int t=1;t<=n;t++)
		{
			pair<int,pair<int,int>> mx={0,{0,0}};
			for(int i=1;i<=n;i++) if(!cws[i])
			{
				for(int k=0;k<n;k++) if(!use[k])
				{
					mx=max(mx,{cnt[i][k],{i,k}});
				}
			}
			printf("%i %i %i\n",mx.second.first,j,mx.second.second);
			assert(mx.first!=0);
			cws[mx.second.first]=1;
			use[mx.second.second]=1;
			cnt[mx.second.first][mx.second.second]--;
			a[mx.second.first][j]=my[mx.second.first][mx.second.second].back();
			my[mx.second.first][mx.second.second].pop_back();
			printf("a[%i][%i]=%i\n",mx.second.first,j,a[mx.second.first][j]);
		}*/
	}
}
int main()
{
	scanf("%i %i",&n,&m);
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%i",&a[i][j]);
	//for(int i=1;i<=n;i++) SolveRow(i);
	Solve();
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) printf("%i%c",a[i][j],j==m?'\n':' ');
	for(int i=1;i<=m;i++) SortCol(i);
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) printf("%i%c",a[i][j],j==m?'\n':' ');
	return 0;
}

Measured memory_bytes: 1520