#include <bits/stdc++.h>
using namespace std;
struct assignment{
vector<vector<int>> main;
int people, sz;
bool generate(int a, int n){
//a*n blocks for n choose 12/a people
//i have big blocks of size a , n such blocks
main.clear();
int rev = 12/a;
for(int i = 0;i<(1<<n);i++){
if(__popcount(i)!=rev)continue;
vector<int> mm;
for(int j = 0;j<n;j++){
if(i&(1<<j)){
for(int k = j*a;k<(j+1)*a;k++){
mm.push_back(k+1);
}
}
}
main.push_back(mm);
if(main.size()>50)return false;
}
people=main.size();
sz=a*n;
return true;
}
assignment combine(assignment other){
int m=0;
int nm = 0;
for(auto thing:other.main)m=max(m, *(max_element(thing.begin(), thing.end())));
for(auto thing:main){
vector<int> topush;
for(auto thing2:thing){
topush.push_back(thing2+m);
nm=max(nm, thing2+m);
}
other.main.push_back(topush);
}
other.sz=nm;
other.people=other.main.size();
return other;
}
};
signed main(){
//min thing+7, 13
vector<assignment> best(51);
vector<int> bestsize(51, 51);
vector<int> as = {1, 2, 3, 4, 6, 12};
for(auto a:as){
for(int n=12/a;n<=(min(12/a+7, 13));n++){
assignment nw;
bool ss=nw.generate(a, n);
if(!ss)continue;
if(nw.sz<bestsize[nw.people]){
bestsize[nw.people]=nw.sz;
best[nw.people]=nw;
}
}
}
for(int i = 2;i<=50;i++){
for(int j = 1;j<i;j++){
assignment x = best[j].combine(best[i-j]);
if(x.sz<bestsize[i]){
bestsize[i]=x.sz;
best[i]=x;
}
}
}
int n;cin>>n;
for(auto thing:best[n].main){
for(auto thing2:thing)cout << thing2-1 << ' ';
cout << '\n';
}
}