#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
#include <cstdio>
#include <limits>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>

using namespace std;

class Board {
    private:
        int size;
        vector<vector<bool>> b;
    public:
        Board(int n) {
            size = n;
            b.resize(n, vector<bool>(n));
        }
        bool visited(int i, int j) {
            return b[i][j];
        }
        void visit(int i, int j) {
            b[i][j] = true;
        }
        void clear() {
            fill(b.begin(), b.end(), vector<bool>(size));
        }
        int get_size() {
            return size;
        }
};

class Knight {
    private:
        Board* bd;
        tuple<int, int> endPos;
        bool end = false;
        int a, b, size;
        int moves = -1;
    public:
        Knight(Board* board, int a_, int b_) {
            bd = board;
            a = a_;
            b = b_;
            size = bd->get_size();
            endPos = make_tuple(size - 1, size - 1);
        }
        void move(tuple<int, int> pos, int count) {
            int i = get<0>(pos);
            int j = get<1>(pos);

            bd->visit(i, j);

            if (end) return;
            if (pos == endPos) {
                moves = count;
                end = true;
            } else {
                
                if ((i+a) < size && (j+b) < size && !bd->visited(i+a, j+b)) {
                    move(make_tuple(i+a, j+b), count + 1);
                }
                
                if ((i+b) < size && (j+a) < size && !bd->visited(i+b, j+a)) {
                    move(make_tuple(i+b, j+a), count + 1);
                } 
                
                if ((i+a) < size && (j-b) >= 0 && !bd->visited(i+a, j-b)) {
                    move(make_tuple(i+a, j-b), count + 1);
                } 
                
                if ((i+b) < size && (j-a) >= 0 && !bd->visited(i+b, j-a)) {
                    move(make_tuple(i+b, j-a), count + 1);
                }
                
                if ((i-a) >= 0 && (j+b) < size && !bd->visited(i-a, j+b)) {
                    move(make_tuple(i-a, j+b), count + 1);
                }
                
                if ((i-b) >= 0 && (j+a) < size && !bd->visited(i-b, j+a)) {
                    move(make_tuple(i-b, j+a), count + 1);
                }
                
                if ((i-a) >= 0 && (j-b) >= 0 && !bd->visited(i-a, j-b)) {
                    move(make_tuple(i-a, j-b), count + 1);
                }

                if ((i-b) >= 0 && (j-a) >= 0 && !bd->visited(i-b, j-a)) {
                    move(make_tuple(i-b, j-a), count + 1);
                }
            }

        }
        int get_moves() {
            return moves;
        }
};


int main(){
    int n;
    cin >> n;
    Board* b = new Board(n);
    for (int i = 1; i < n; i++) {
        for (int j = 1; j < n; j++) {
            Knight* k = new Knight(b, i, j);
            k->move(make_tuple(0, 0), 0);
            cout << k->get_moves() << " ";
            b->clear();
        }
        
        cout << endl;
    }
    return 0;
}