//全排列的回溯,我还没看懂,如何实现的回溯
//一直以为排列的时候,数据会互相干扰,发现都是一次性 一条龙找完,然后直接输出,不存在中途又跑另外一个dfs的鬼畜情况

#include <iostream>
#include <set>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int M = 1e3 + 1;
int a[M];//存储最后的数据
int vis[M];//存储
int n;
void print()//输出函数
{
    for (int i = 1; i <= n; i++) {
        printf("%5d", a[i]);
    }
    cout << endl;
}
inline void dfs(int k) {
    if (k == n) {//当格子数达到需求的就可以跑路了
        print();
        return;
    }
    for (int i = 1; i <= n; i++) {
        if (vis[i] == 0) {//判断这个数是否用过
            //这里之前写了k++,在一个dfs中k的值是不能发生变化的,发生变换的只能是在写函数时+1,往下一个走
            //如果用了k++,这里我们模拟一下,n=3的情况
            //k从0开始 a[1]=1,vis[1]=1,dfs(1),vis[1]=0,
            //再跑k=1开始,同理 直接就输出了1 2 3 根本无回溯
            // 当i到了2,虽然vis 依旧全为0,但是a[1]的情况就永远无法改变
            //若是把k+1放在括号里
            //继续模拟n=3的情况,a[1]=1,vis[1]=1,dfs(1),在这里,他会一直跑
            //因为k代表的是哪个格子里放哪个数,所以在i循环里,他不能随i循环的变化而变化

            a[k + 1] = i;
            vis[i] = 1;
            dfs(k + 1);
            vis[i] = 0;


        }
    }
}
int main()
{
    cin >> n;
    dfs(0);//要从0开始,表示一开始内没有填充物,三个格子上并没有任何数据
    return 0;
}