//dennismv

#include <iostream>

#include <vector>

#include <iomanip>

#include <cmath>

using namespace std;

#define FOR(i,n) for (int i=0;i<(int)n;i++)

#define FORN(i,a,b) for (int i=a;i<=b;i++)

const int MAX=10;

 

int primes[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199};

const int numPrimes=46;

int storedGrid[MAX][MAX];

bool gridIsStored;

int minSum;

 

bool checkPlacement(int grid[][MAX],vector<int> &isPrime,int row,int col)

{

      int center=grid[row][col];

      if (row-1>=0 && !isPrime[center+grid[row-1][col]]) return false;

      if (col-1>=0 && !isPrime[center+grid[row][col-1]]) return false; 

      return true;

}

 

bool optimalSum(int grid[][MAX],int g)

{

      int sum=0;

      FOR(i,g)FOR(j,g)sum+=grid[i][j];

      int optimalSum=g*g*(1+g*g)/2;

      return (sum==optimalSum);

}

 

void showGrid(int grid[][MAX],int g,int count)

{

      cout<<"Matt, here is puzzle #"<<count<<":"<<endl;

 

      int fieldWidth=0;

      FOR(i,g)FOR(j,g) if (grid[i][j]>fieldWidth) fieldWidth=grid[i][j];

      fieldWidth=(int)floor(log((double)fieldWidth)/log((double)10)+1);

      FOR(i,g)

      {

            cout<<setw(fieldWidth)<<grid[i][0];

            FORN(j,1,g-1) cout<<setw(fieldWidth+1)<<grid[i][j];

            cout<<endl;

      }

}

 

bool minGridSum(int grid[][MAX],int g)

{

      int sum=0;

      FOR(i,g)FOR(j,g)sum+=grid[i][j];

     

      if (minSum<=sum) return false;

      minSum=sum;

      return true;

}

 

bool placeNext(int grid[][MAX],int g,bool used[],vector<int> &isPrime,int gridPlace=0)

{

      if (gridPlace==g*g)    

      {

            if (optimalSum(grid,g))

            {

                  //cout<<"OPTIMALE!\n";

                  return true;

            }

           

            if (minGridSum(grid,g)) //found next smallest grid!!

            {

                  //store grid!

                  //showGrid(grid,g,1);

                  gridIsStored=true;

                  FOR(i,g)FOR(j,g) storedGrid[i][j]=grid[i][j];

            }

 

            return false;

      }

      //stuff

      int final;

      if (g>4) final=g*g;

      else final=2*g*g;

      FOR(i,final)

      {    

            if (used[i]) continue;

            used[i]=true;

            grid[gridPlace/g][gridPlace%g]=i+1;

            if (checkPlacement(grid,isPrime,gridPlace/g,gridPlace%g) && placeNext(grid,g,used,isPrime,gridPlace+1)) return true;

            grid[gridPlace/g][gridPlace%g]=0;

            used[i]=false;

      }

      return false;

}

 

int main()

{

      int grid[MAX][MAX];

      bool used[MAX*MAX];

 

      //get prime index ready

      vector<int> isPrime(primes[numPrimes-1]+1);

      FOR(i,numPrimes) isPrime[primes[i]]=true;

 

      int n,count=1,g;

      while (cin>>g>>n && g!=0)

      {

            gridIsStored=false;

            minSum=300000;                //min sum

            FOR(i,100) used[i]=0;

            grid[0][0]=n;                 //place n in top left

            used[n-1]=true;               //and mark it used

            //place remaining elements

            if (count>1) cout<<endl;

            if (placeNext(grid,g,used,isPrime,1)) showGrid(grid,g,count);     //optimal grid

            else if (gridIsStored) showGrid(storedGrid,g,count);              //optimized grid (not optimal but as far as we could get)

            else cout<<"Yo, Matt!  That puzzle #"<<count<<", it was not cool!"<<endl;       //sorry,ya no grid Matt!

            used[n-1]=false;

            count++;

      }

}