#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<cmath>

using namespace std;

//60min
//耗时于改bug
/*************************
题意:
给一个序列
求螺旋矩阵。。常见模拟题
矩阵的行列相差最小,相加为N
*************************/

/************************
求解要点:
1.求行列数时,用n开根号,找到离n最近的整数
接着再把最大的赋给m即可。

2.坐标=i*n+m
事先初始化ans数组为-1
按螺旋的规律进行赋值,要连续设置4个while循环
注意先自己在纸上计算好i,j的关系
再去写
不要先写再改,太费时间了。
************************/

/***********************
笔记:

*********************/


#define M 20000

bool cmp(int a,int b)
{
return a>b;
}
int num[M],ans[M];
int main()
{
int n,i,m;
int numn;
scanf("%d",&n);
numn=n;
for(i=0;i<n;i++)
scanf("%d",&num[i]);
sort(num,num+n,cmp);

for(i=0;i<=numn;i++)
ans[i]=-1;
int fm=int(sqrt(double(n)));
for(i=fm;i<=n;i++)
{
if(n%i==0)
{
m=i;
n=n/i;
break;
}
}
if(m<n)
swap(m,n);
//cout<<n<<" "<<m<<endl;

int j=-1;
i=0;
int k=0;
//cout<<num[0]<<endl;
while(k<numn)
{
j++;
while(k<numn)
{
//printf("1:ans[%d]=num[%d]=%d\n,\n",i*n+j,k,num[k]);
ans[i*n+j]=num[k++];
if(j+1==n || ans[i*n+j+1]!=-1)
break;
else j++;
}

i++;
while(k<numn)
{
//printf("2:ans[%d]=num[%d]=%d\n,\n",i*n+j,k,num[k]);
ans[i*n+j]=num[k++];
if(i+1==m || ans[(i+1)*n+j]!=-1)
break;
else i++;
}

j--;
while(k<numn)
{
//printf("3:ans[%d]=num[%d]=%d\n,\n",i*n+j,k,num[k]);
ans[i*n+j]=num[k++];
if(j-1<0 || ans[i*n+j-1]!=-1)
break;
else j--;
}

i--;
while(k<numn)
{
//printf("4:ans[%d]=num[%d]=%d\n,\n",i*n+j,k,num[k]);
ans[i*n+j]=num[k++];
if(i-1<0 || ans[(i-1)*n+j]!=-1)
break;
else i--;
}

}

for(i=0;i<m;i++)
{
printf("%d",ans[i*n]);
for(j=1;j<n;j++)
{
printf(" %d",ans[i*n+j]);
}
cout<<endl;
}
return 0;
}