#!/bin/python

import sys

class graph(object):
    """unweighted directed graph
    """

    def __init__(self):
        """set _vmap to and _vprev an empty python dict
        all vertex are represented by a simple index

        _vmap: {vertex x: x's adjacency list}
        _vprev: {vertex x: x's prev vertex computed by bfs routine}
        """
        self._vmap = {};
        self._vprev = {};

    def add_edge(self, start, end):
        """add an edge to the graph
        """
        if self._vmap.has_key(start):
            self._vmap[start].append(end)
        else:
            self._vmap[start] = [end]

    def bfs_shortest(self, start):
        """one-source shortest-path algorithm
        """
        queue = [start]

        self._vprev[start] = None

        while len(queue) != 0:
            v = queue[0]
            queue.pop(0)

            if self._vmap.has_key(v):
                v_adj = self._vmap[v]
            else:
                continue

            for nextv in v_adj:
                if self._vprev.has_key(nextv):# and self._vprev[nextv] is not None:
                    # nextv has already found its parent""
                    continue
                else:
                    queue.append(nextv)
                    self._vprev[nextv] = v

    def get_path(self, end):
        """return the shortest path as a python list
        """
        v = end;
        path = []
        while self._vprev.has_key(v) and self._vprev[v] is not None:
            path.insert(0, v)
            v = self._vprev[v]

        if self._vprev.has_key(v):
            path.insert(0, v)   # insert the start point to the path
        else:
            #print "destination %d is not exist or unreachable" % v
            pass

        return path

class chessboard(object):
    """a chessboard of size n*n class
    """

    def __init__(self, n, npx,npy):
        """build the internal graph representation of the chessboard

        Arguments:
        - `n`: size of the chessboard
        """
        self._size = n
        self._board = graph()

        next_point = ((npx,npy), (npx, -1*npy), \
                      (npy,npx), (npy, -1*npx), \
                      (-1*npx,npy), (-1*npx,-1*npy), \
                      (-1*npy,npx), (-1*npy,-1*npx))
        #next_point = ((2, 1), (2, -1), \
        #              (1, 2), (1, -2), \
        #              (-2, 1), (-2, -1), \
        #              (-1, 2), (-1, -2))

        for x in range(n):
            for y in range(n):
                start = self.point2index(x, y)
                for dx, dy in next_point:
                    nx = x + dx
                    ny = y + dy

                    if self.is_valid(nx, ny):
                        end = self.point2index(nx, ny)
                        self._board.add_edge(start, end)

    def is_valid(self, x, y):
        """whether or not point (x, y) is valid in the chessboard
        """
        return 0 <= x < self._size and 0 <= y < self._size

    def point2index(self, x, y):
        """convert a chessboard point to the internal graph vertex index
        """
        return x * self._size + y

    def index2point(self, p):
        """convert the internal graph vertex index back to a chessboard point
        """
        return (p / self._size, p % self._size)

    def solve_knight(self, x, y):
        """just solve it
        """
        start = self.point2index(x, y)
        end = self.point2index(self._size - 1, self._size - 1)
        self._board.bfs_shortest(start)
        path = [self.index2point(x) for x in self._board.get_path(end)]
        return [(x + 1, y + 1) for x, y in path]

def calcSol(N,npx,npy):
    """main routine
    """
    # g = graph()
    # g.add_edge(1, 2)
    # g.add_edge(1, 3)
    # g.add_edge(2, 3)
    # g.add_edge(3, 4)
    # g.bfs_shortest(1)
    # print g.get_path(4)

    #if len(sys.argv) != 4:
    #    print """Wrong arguments! Usage: ./knight.py N x y
    #    """
    #    return -1

    #N = int(sys.argv[1])
    #x = int(sys.argv[2])
    #y = int(sys.argv[3])

    chess = chessboard(N,npx,npy)

    #print chess.solve_knight(x - 1, y - 1)

    return len(chess.solve_knight(0, 0))-1


n = int(raw_input().strip())
# your code goes here
w, h = n-1, n-1;
Matrix = [[0 for x in range(w)] for y in range(h)]
for i in range(n-1):
    for j in range(n-1):
        Matrix[i][j] = calcSol(n,i+1,j+1)#i,j,n-1)
        #print (str(i+1)+" "+str(j+1)+" "+str(calcSol(n,i+1,j+1)))
#print (Matrix)
#print('\n'.join([''.join(['{:2}'.format(item) for item in row]) 
#      for row in Matrix]))
print('\n'.join([' '.join(['{:1}'.format(item) for item in row]) 
      for row in Matrix]))