//
//  KnightLChessboard.cpp
//  HR
//
//  Created by Admin on 10/02/2017.
//  Copyright © 2017 Jose. All rights reserved.
//
#include <cstring>
#include <string.h>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <vector>
#include <set>
#include <complex>
#include <list>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <string>


using namespace std;

#define pb push_back
#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(),v.rend()
#define sz size()
#define rep(i,m) for(int i=0;i<(int)(m);i++)
#define rep2(i,n,m) for(int i=n;i<(int)(m);i++)
#define For(it,c) for(__typeof(c.begin()) it=c.begin();it!=c.end();++it)
#define mem(a,b) memset(a,b,sizeof(a))
#define mp make_pair
#define F first
#define S second
#define pb push_back
#define forn(i, n) for(int i = 0 ; (i) < (n) ; ++i)
#define eprintf(...) fprintf(stderr, __VA_ARGS__),fflush(stderr)
#define pw(x) (1LL<<(x))
#define DBGV(vari) cout << #vari<< " = "<< (vari) <<endl;
#define DBGList(list) for(auto vari: list)cout<<" = "<<(vari)<<";"; cout<<endl;

typedef stringstream ss;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
typedef vector<string> vs;
typedef vector<int> vi;
typedef vector<double> vd;
typedef vector<vector<int> > vvi;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vll;
typedef pair<double,double> pdd;
typedef pair<long,long> pll;
typedef vector<pll> vpll;
typedef vector<vpll> vvpll;
//const int oo = (int) 1e9;
const double PI = 2 * acos(0);
//const double eps = 1e-9;
const ll inf=1e10;


int n;
struct move{
    int a,x,y;
    move(int a, int x, int y){
        this->a=a;
        this->x=x;
        this->y=y;
       
    }
} ;

typedef struct move move;

bool operator<(const struct move &a, const struct move &b) {
    return a.a<b.a;
}

int solve(int i, int j){ // i<=j
    
    
    int p=n-1;
    //if(p%i!=0 || p%j!=0) return -1;
    //return p/i;
    //int c=0;
    priority_queue<struct move*> q;
    unordered_set<int> vis;
    struct move* sta= new struct move(0,0,0);
    q.push(sta);
    vis.insert(0);
    while (!q.empty()) {
        struct move* st=q.top(); q.pop();
        int a=st->a,  x=st->x,  y=st->y;
        if(j==3){
            //DBGV(a) DBGV(x) DBGV(y) cout<<endl;
        }
        //DBGV(a) DBGV(x) DBGV(y)
        if(x==p && y==p) return -a;
        for(int k=0;k<8;k++){
            int dx=k<4?i:j, dy=i+j-dx;
            if(k%2) dx=-dx;
            if(k/2%2) dy=-dy;
            //DBGV(dx) DBGV(dy) cout<<endl;
            if(vis.find((x+dx)*n+y+dy)==vis.end() && x+dx<n && x+dx>=0 && y+dy<n && y+dy>=0){
                struct move* nm= new struct move(a-1,x+dx,y+dy);
                //DBGV(a) DBGV(x+dx) DBGV(y+dy)
                q.push(nm);
                vis.insert(n*(x+dx)+y+dy);
            }
        }
    }
    return -1;
    //if(p%i!=0 || p%j!=0) return -1;
    //return p/i;
    
}
int solve2(int i, int j){ // i<=j

    unordered_set<int> vis;
    int p=n-1;
    priority_queue<struct move> q;
    struct move sta= *(new struct move(0,0,0));
    vis.insert(0);
    q.push(sta);
    while (!q.empty()) {
        struct move st=q.top(); q.pop();
        int a=st.a,  x=st.x,  y=st.y;
        if(j==3) {
         //DBGV(a) DBGV(x) DBGV(y)
        }
        if(x==p && y==p) return -a;
        for(int k=0;k<8;k++){
            int dx=k<4?i:j, dy=i+j-dx;
            if(k%2) dx=-dx;
            if(k/2%2) dy=-dy;
            if(vis.find((x+dx)*n+y+dy)==vis.end() && x+dx<n && x+dx>=0 && y+dy<n && y+dy>=0){
                struct move nm= *new struct move(a-1,x+dx,y+dy);
                q.push(nm);
                vis.insert(n*(x+dx)+y+dy);
            }
        }
    }
    return -1;
}

int main(){
    cin>>n;
    for(int i=1;i<n;i++){
        for(int j=1;j<n;j++){
            printf("%d%c",solve2(i,j) , j+1==n?'\n':' ');
        }
    }
}