import java.util.*;
import java.io.*;

public class Solution {
	public static void main(String[] args) {

		Kattio io = new Kattio(System.in, System.out);

		int n = io.getInt();
		int size = n*n;
		
		int[] dist = new int[size];
		boolean[] visited = new boolean[size];
		int[][] edges = new int[size][size];
		

		int[][] answer = new int[n][n];
		
		for (int a = 1; a<n; a++) {
			for (int b=a; b<n; b++) {
				answer[a][b] = solve(io, n, size, dist, visited, edges, a, b);
				answer[b][a] = answer[a][b];
			}
		}
		
		for (int a = 1; a<n; a++) {
			for (int b=1; b<n; b++) {
				io.print(answer[a][b]);
				io.print(' ');
			}
			io.println();
		}
		
		io.close();
	}

	private static int solve(Kattio io, int n, int size, int[] dist, boolean[] visited,
			int[][] edges, int a, int b) {
		Arrays.fill(dist, -1);
		Arrays.fill(visited, false);
		for (int i = 0; i < size; i++) {
			Arrays.fill(edges[i], -1);
		}
		
		for (int i1 = 0; i1 < n; i1++) {
			for (int j1 = 0; j1 < n; j1 ++) {
				int i2,j2;
				i2 = i1+a;
				j2 = j1+b;
				
				addEdge(n, edges, i1, j1, i2, j2);

				i2 = i1+a;
				j2 = j1-b;
				
				addEdge(n, edges, i1, j1, i2, j2);

				i2 = i1-a;
				j2 = j1+b;
				
				addEdge(n, edges, i1, j1, i2, j2);

				i2 = i1-a;
				j2 = j1-b;
				
				addEdge(n, edges, i1, j1, i2, j2);

				i2 = i1+b;
				j2 = j1+a;
				
				addEdge(n, edges, i1, j1, i2, j2);

				i2 = i1+b;
				j2 = j1-a;
				
				addEdge(n, edges, i1, j1, i2, j2);

				i2 = i1-b;
				j2 = j1+a;
				
				addEdge(n, edges, i1, j1, i2, j2);

				i2 = i1-b;
				j2 = j1-a;
				
				addEdge(n, edges, i1, j1, i2, j2);

			}
		}
//		
//		for (int i = 0; i < edges.length; i++) {
//			io.println(Arrays.toString(edges[i]));
//		}
//		io.println();
//
//		int row = 1;
//		for (int i1 = 0; i1 < n; i1++) {
//			for (int j1 = 0; j1 < n; j1 ++) {
//				io.print(edges[row][i1*n+j1] > 0 ? 'x' : '.');
//			}
//			io.println();
//		}
//		io.println();

		dist[0] = 0;

		PriorityQueue<Integer> pq = new PriorityQueue<>(
				Comparator.comparing(i -> dist[i] < 0 ? Long.MAX_VALUE : dist[i]));

		pq.add(0);

		while (!pq.isEmpty()) {
			int cur = pq.poll();
			if (visited[cur])
				continue;
			visited[cur] = true;

			for (int v2 = 0; v2 < size; v2++) {
				if (edges[cur][v2] < 0)
					continue;

				int d = dist[cur] + edges[cur][v2];
				int d2 = dist[v2];
				if (d2 < 0 || d < d2) {
					dist[v2] = d;
				}
				pq.add(v2);
			}

		}


		int distab = dist[size-1];
		return distab;
	}

	private static void addEdge(int n, int[][] edges, int i1, int j1, int i2, int j2) {
		if (0 <= i2 && i2 < n && 0 <= j2 && j2 < n) {
			edges[i1*n+j1][i2*n+j2] = 1;
		}
	}

	static class Kattio extends PrintWriter {
		public Kattio(InputStream i) {
			super(new BufferedOutputStream(System.out));
			r = new BufferedReader(new InputStreamReader(i));
		}

		public Kattio(InputStream i, OutputStream o) {
			super(new BufferedOutputStream(o));
			r = new BufferedReader(new InputStreamReader(i));
		}

		public boolean hasMoreTokens() {
			return peekToken() != null;
		}

		public int getInt() {
			return Integer.parseInt(nextToken());
		}

		public double getDouble() {
			return Double.parseDouble(nextToken());
		}

		public long getLong() {
			return Long.parseLong(nextToken());
		}

		public String getWord() {
			return nextToken();
		}

		private BufferedReader r;
		private String line;
		private StringTokenizer st;
		private String token;

		private String peekToken() {
			if (token == null)
				try {
					while (st == null || !st.hasMoreTokens()) {
						line = r.readLine();
						if (line == null)
							return null;
						st = new StringTokenizer(line);
					}
					token = st.nextToken();
				} catch (IOException e) {
				}
			return token;
		}

		private String nextToken() {
			String ans = peekToken();
			token = null;
			return ans;
		}
	}

}