#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

int moves(int a, int b, int n) {
    
    if (a > b) {
        return moves(b, a, n);
    }
    
    // number of moves to get to a square
    vector<vector<int>> nummoves(n, vector<int>(n, -1));

    queue<int> q;

    q.push(0);
    nummoves[0][0] = 0;
    
    // only 25 max, so loop? or search necessary? search really necessary!
    while (nummoves[n-1][n-1] == -1 && !q.empty()) {
        int i = q.front() % (n);
        int j = q.front() / (n);
        // cout << i << " " << j << " " << nummoves[i][j] << endl;
        q.pop();
        vector<int> xs = {i + a, i - a, i + a, i - a, i + b, i + b, i - b, i - b};
        vector<int> ys = {j + b, j + b, j - b, j - b, j + a, j - a, j + a, j - a};
        for (int k = 0; k < 8; k++) {
            // check range
            if (xs[k] < 0 || xs[k] >= n || ys[k] < 0 || ys[k] >= n) {
                continue;
            }
            if ((nummoves[xs[k]][ys[k]] == -1) || (nummoves[xs[k]][ys[k]] > nummoves[i][j] + 1)) {
                nummoves[xs[k]][ys[k]] = nummoves[i][j] + 1;
                q.push(xs[k] + (n) * ys[k]);
            }
        }
    }
    // cout << nummoves[n-1][n-1] << endl;
    return nummoves[n-1][n-1];
}

int main() {
    int n;
    cin >> n;
    
    for (int a = 1; a < n; a++) {
        for (int b = 1; b < n; b++) {
            cout << moves(a, b, n) << " ";
        }
        cout << endl;
    }
    return 0;
}