#include <iostream>
	#include <algorithm>
	#include <vector>
	#include <array>

	struct Point
	{
		size_t x;
		size_t y;
		Point() : x(0), y(0) {}
		Point(size_t x, size_t y) : x(x), y(y) {}

		Point operator+(const Point& p) const
		{
			return Point(x + p.x, y + p.y);
		}

		bool operator==(const Point& p) const
		{
			return x == p.x && y == p.y;
		}
	};

	const std::array<Point, 4> clockwise {
		Point(+1, 0), //right
		Point(0, +1), //down
		Point(-1, 0), //left
		Point(0, -1), //up
	};

	const std::array<Point, 4> counterClockwise {
		Point(0, +1), //down
		Point(+1, 0), //right
		Point(0, -1), //up
		Point(-1, 0), //left
	};

	struct Grid
	{
		std::vector<std::vector<int>> grid;
		size_t size;

		Grid(size_t size)
		{
			this->size = size;
			for(size_t i = 0; i < size; i++)
			{
				grid.push_back(std::vector<int>(size));
				std::fill(grid[i].begin(), grid[i].end(), 0);
			}
		}

		bool withinBounds(const Point& p)
		{
			return 0 <= p.x && p.x < size && 0 <= p.y && p.y < size;
		}

		void fill(bool reverse)
		{
			Point current(0, 0);
			size_t directionIndex = 0;
			auto direction = reverse ? counterClockwise : clockwise;
			for(int number = 1, end = size * size; number <= end; number++)
			{
				grid[current.y][current.x] = number;
				auto next = current + direction[directionIndex];
				if(!withinBounds(next) || grid[next.y][next.x] != 0)
				{
					directionIndex = (directionIndex + 1) % 4;
					next = current + direction[directionIndex];
				}
				current = next;
			}
		}

		friend std::ostream& operator<<(std::ostream& out, const Grid& g);
	};

	std::ostream& operator<<(std::ostream& out, const Grid& g)
	{
		for(size_t y = 0; y < g.size; y++)
		{
			for(size_t x = 0; x < g.size; x++)
			{
				out << g.grid[y][x] << '\t';
			}
			out << std::endl;
		}
		return out;
	}

	int main()
	{
		int n;
		std::string direction;
		std::cin >> n;
		std::cin >> direction;

		Grid grid(n);
		grid.fill(direction == "reverse");
		std::cout << grid << std::endl;
	}