#include using namespace std; using ll=long long; //#define int ll #define rng(i,a,b) for(int i=int(a);i=int(a);i--) #define per(i,b) gnr(i,0,b) #define pb push_back #define eb emplace_back #define a first #define b second #define bg begin() #define ed end() #define all(x) x.bg,x.ed #define si(x) int(x.size()) #ifdef LOCAL #define dmp(x) cerr<<__LINE__<<" "<<#x<<" "< bool chmax(t&a,u b){if(a bool chmin(t&a,u b){if(b using vc=vector; template using vvc=vc>; using pi=pair; using vi=vc; template ostream& operator<<(ostream& os,const pair& p){ return os<<"{"< ostream& operator<<(ostream& os,const vc& v){ os<<"{"; for(auto e:v)os< void dmpr(ostream&os,const T&t,const Args&... args){ os< ostream& operator<<(ostream&os,const array&a){ return os<(all(a)); } template void print_tuple(ostream&,const T&){ } template void print_tuple(ostream&os,const T&t){ if(i)os<<","; os<(t); print_tuple(os,t); } template ostream& operator<<(ostream&os,const tuple&t){ os<<"{"; print_tuple<0,tuple,Args...>(os,t); return os<<"}"; } template void print(t x,int suc=1){ cout<>i; return i; } vi readvi(int n,int off=0){ vi v(n); rep(i,n)v[i]=read()+off; return v; } pi readpi(int off=0){ int a,b;cin>>a>>b; return pi(a+off,b+off); } template void print(const pair&p,int suc=1){ print(p.a,2); print(p.b,suc); } template void print(const vector&v,int suc=1){ rep(i,v.size()) print(v[i],i==int(v.size())-1?suc:2); } string readString(){ string s; cin>>s; return s; } template T sq(const T& t){ return t*t; } //#define CAPITAL void yes(bool ex=true){ #ifdef CAPITAL cout<<"YES"<<"\n"; #else cout<<"Yes"<<"\n"; #endif if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } void no(bool ex=true){ #ifdef CAPITAL cout<<"NO"<<"\n"; #else cout<<"No"<<"\n"; #endif if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } void possible(bool ex=true){ #ifdef CAPITAL cout<<"POSSIBLE"<<"\n"; #else cout<<"Possible"<<"\n"; #endif if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } void impossible(bool ex=true){ #ifdef CAPITAL cout<<"IMPOSSIBLE"<<"\n"; #else cout<<"Impossible"<<"\n"; #endif if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } constexpr ll ten(int n){ return n==0?1:ten(n-1)*10; } const ll infLL=LLONG_MAX/3; #ifdef int const int inf=infLL; #else const int inf=INT_MAX/2-100; #endif int topbit(signed t){ return t==0?-1:31-__builtin_clz(t); } int topbit(ll t){ return t==0?-1:63-__builtin_clzll(t); } int botbit(signed a){ return a==0?32:__builtin_ctz(a); } int botbit(ll a){ return a==0?64:__builtin_ctzll(a); } int popcount(signed t){ return __builtin_popcount(t); } int popcount(ll t){ return __builtin_popcountll(t); } bool ispow2(int i){ return i&&(i&-i)==i; } ll mask(int i){ return (ll(1)< void mkuni(vc&v){ sort(all(v)); v.erase(unique(all(v)),v.ed); } ll rand_int(ll l, ll r) { //[l, r] #ifdef LOCAL static mt19937_64 gen; #else static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count()); #endif return uniform_int_distribution(l, r)(gen); } template void myshuffle(vc&a){ rep(i,si(a))swap(a[i],a[rand_int(0,i)]); } template int lwb(const vc&v,const t&a){ return lower_bound(all(v),a)-v.bg; } vvc readGraph(int n,int m){ vvc g(n); rep(i,m){ int a,b; cin>>a>>b; //sc.read(a,b); a--;b--; g[a].pb(b); g[b].pb(a); } return g; } vvc readTree(int n){ return readGraph(n,n-1); } //sz: size of the matching //mt[i]: matching mate of the vertex i //VERIFY: yosupo //NEERC2018B //Petrozavodsk 2019w Day1 A struct maxmatching{ struct E{int a,b;}; const vvc&g; int n,sz; vi p,t,mt; vc f; int non(int v){ return t[v]!=sz||p[v]==-1?v:(p[v]=non(p[v])); } void R(int a,int b){ int d=mt[a]; mt[a]=b; if(d==-1||mt[d]!=a)return; if(f[a].b==-1){ mt[d]=f[a].a; R(f[a].a,d); }else{ R(f[a].a,f[a].b); R(f[a].b,f[a].a); } } bool arg(int rt){ queue q; t[rt]=sz; p[rt]=-1; f[rt]=E{-1,-1}; q.push(rt); while(!q.empty()){ int a=q.front();q.pop(); for(auto b:g[a]){ if(b==rt)continue; if(mt[b]==-1){ mt[b]=a; R(a,b); return true; } if(t[b]==sz){ int x=non(a),y=non(b); if(x==y)continue; int z=rt; while(x!=rt||y!=rt){ if(y!=rt)swap(x,y); if(f[x].a==a&&f[x].b==b){ z=x; break; } f[x]=E{a,b}; x=non(f[mt[x]].a); } for(auto v:{non(a),non(b)}){ while(v!=z){ t[v]=sz; p[v]=z; q.push(v); v=non(f[mt[v]].a); } } continue; } if(t[mt[b]]==sz)continue; f[b]=E{-1,-1}; t[mt[b]]=sz; p[mt[b]]=b; f[mt[b]]=E{a,-1}; q.push(mt[b]); } } return false; } maxmatching(const vvc&gg):g(gg),n(g.size()),sz(0), p(n),t(n,-1),mt(n,-1),f(n){ rep(i,n)if(mt[i]==-1) sz+=arg(i); } //codechef HAMILG //res[i]=最大マッチングに必ず含まれるべき頂点なら 1, そうでないなら 0 vi need(){ rep(i,n)if(mt[i]==-1) arg(i); vi res(n); rep(i,n)res[i]=(mt[i]!=-1&&t[i]!=sz); return res; } }; bool adj(pi x,pi y){ auto [a,b]=x; auto [d,e]=y; int g=abs(a-d),h=abs(b-e); if(g==1&&h==2)return true; if(h==1&&g==2)return true; return false; } vi baka{640123342,149795075,435766641,962740521,655148792,415754176,376479654,870002679,720108329,159621518,11174811,387483131,378665771,561039471,331699185,126721473,443148615,932333129,537805256,560931851,365487476,533804022,740623840,763546631,538506276,874001638,94913828,147131095,947798556,252504454,124726188,728150503,340648925,846675740,753540696,201741433,457098100,242736752,101613178,179436008,422379147,716728797,130960454,582731547,879298814,327320790,601101480,712029853,666028075,}; int seed; using T=tuple; vc dxy{}; vc sub(int n){ int s=0; vvc idx(n,vi(n,-1)); rep(i,n)rep(j,n){ if(pi(i,j)==pi(0,0))continue; if(pi(i,j)==pi(n-1,n-1))continue; idx[i][j]=s++; } vvc g(s); rep(i,n)rep(j,n){ if(pi(i,j)==pi(0,0))continue; if(pi(i,j)==pi(n-1,n-1))continue; for(auto [x,y]:dxy){ x+=i; y+=j; if(inc(0,x,n-1)&&inc(0,y,n-1)){ if(pi(x,y)==pi(0,0))continue; if(pi(x,y)==pi(n-1,n-1))continue; g[idx[i][j]].pb(idx[x][y]); } } } //find a cycle vc lf; rep(step,n/2-1){ int x=n-1-step*2,y=step*2; lf.eb(x-2,y+1); lf.eb(x,y+2); lf.eb(x-1,y); if(step pos; rep(i,n)rep(j,n)if(idx[i][j]!=-1)pos.eb(i,j); while(1){ //int seed=rand_int(0,ten(9)); mt19937 rnd(seed); vc vis(s); for(auto i:c)vis[i]=true; vc ans; int cur=0; rep(i,si(c)){ int v=c[i]; vi tmp; while(1){ vis[v]=true; tmp.pb(v); int mn=inf; vi buf; for(auto j:g[v])if(!vis[j]){ int cnt=0; for(auto k:g[j])if(!vis[k])cnt++; if(mn>cnt){ buf.clear(); mn=cnt; } if(mn==cnt){ buf.pb(j); } } if(buf.empty())break; v=buf[rnd()%si(buf)]; } for(auto w:tmp){ ans.eb(pos[w].a,pos[w].b,cur); } cur^=1; reverse(all(tmp)); for(auto w:tmp){ ans.eb(pos[w].a,pos[w].b,cur); } } if(si(ans)==2*n*n-4){ baka.pb(seed); return ans; } } } bool adj(T x,T y){ auto [a,b,c]=x; auto [d,e,f]=y; if(c!=f)return pi(a,b)==pi(d,e); int g=abs(a-d),h=abs(b-e); if(g==1&&h==2)return true; if(h==1&&g==2)return true; return false; } void check(int n,vc z){ assert(si(z)==2*n*n-4); for(auto [a,b,c]:z){ assert(inc(0,a,n-1)); assert(inc(0,b,n-1)); assert(inc(0,c,1)); assert(pi(a,b)!=pi(0,0)); assert(pi(a,b)!=pi(n-1,n-1)); } rep(i,si(z)){ assert(adj(z[i],z[(i+1)%si(z)])); } mkuni(z); assert(si(z)==2*n*n-4); } void slv(){ } signed main(){ cin.tie(0); ios::sync_with_stdio(0); cout<>n; seed=baka[(n-4)/2]; auto ans=sub(n); for(auto [i,j,k]:ans){ cout<