#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 10010;
int a[N], g[N][N];
bool isPrime(int x){
if( x<=1 ) return false;
if( x==2 || x==3 ) return true;
if( x%6!=1 && x%6!=5 ) return false;
for( int i=5; i<=x/i; i++ ){
if( x%i==0 ) return false;
}
return true;
}
int main(){
int k, n, m;
scanf("%d", &k);
for( int i=0; i<k; i++ ) scanf("%d", &a[i]);
sort(a, a+k, greater<int>());
if( k==1 || isPrime(k) ){ //质数输出一列
for( int i=0; i<k; i++ ){
printf("%d\n", a[i]);
}
}
else{
int t = sqrt(k);
for( int i=t; i>1; i-- ){
if( k%i==0 ){
n=i, m=k/i;
break;
}
}
t = 0;
int l=0, r=n-1, u=0, d=m-1; //螺旋边界
int x=0, y=0;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int p = 0;
while( t<k ){
g[x][y] = a[t++];
x += dx[p], y += dy[p];
if( y>r ){ //向右走到头,转向下走
u++, y--, x++;
p = 1;
}
else if( x>d ){ //向下走到头,转向左走
r--, x--, y--;
p = 2;
}
else if( y<l ){ //向左走到头,转向上走
d--, y++, x--;
p = 3;
}
else if( x<u ){ //向上走到头,转向右走
l++, x++, y++;
p = 0;
}
}
for( int i=0; i<m; i++ ){
for( int j=0; j<n; j++ ){
if( j ) printf(" ");
printf("%d", g[i][j]);
}
puts("");
}
}
return 0;
}